Class | Gem::Specification |
In: |
lib/rubygems/specification.rb
|
Parent: | Object |
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 = 'example' s.version = '1.0' s.summary = 'Example gem specification' ... end
For a great way to package gems, use Hoe.
NONEXISTENT_SPECIFICATION_VERSION | = | -1 | The the version number of a specification that does not specify one (i.e. RubyGems 0.7 or earlier). | |
CURRENT_SPECIFICATION_VERSION | = | 3 |
The specification version applied to any new Specification instances created. This should
be bumped whenever something in the spec format changes.
Specification Version History: spec ruby ver ver yyyy-mm-dd description -1 <0.8.0 pre-spec-version-history 1 0.8.0 2004-08-01 Deprecated "test_suite_file" for "test_files" "test_file=x" is a shortcut for "test_files=[x]" 2 0.9.5 2007-10-01 Added "required_rubygems_version" Now forward-compatible with future versions 3 1.3.2 2009-01-03 Added Fixnum validation to specification_version |
name | [RW] | This gem‘s name |
require_paths | [RW] |
Paths in the gem to add to $LOAD_PATH when this gem is activated.
The default [‘lib’] is typically sufficient. |
rubygems_version | [RW] |
The version of RubyGems used to create this gem.
Do not set this, it is set automatically when the gem is packaged. |
specification_version | [RW] |
The Gem::Specification version of this
gemspec.
Do not set this, it is set automatically when the gem is packaged. |
summary | [R] |
A short summary of this gem‘s description. Displayed in `gem list
-d`.
The description should be more detailed than the summary. For example, you might wish to copy the entire README into the description. |
version | [R] | This gem‘s version |
loaded | -> | loaded? |
activated | -> | activated? |
activated | [RW] | True when this gemspec has been activated. This attribute is not persisted. |
autorequire | [RW] |
Autorequire was used by old RubyGems to automatically require a file.
Deprecated: It is neither supported nor functional. |
bindir | [RW] | The path in the gem for executable scripts. Usually ‘bin‘ |
cert_chain | [RW] | The certificate chain used to sign this gem. See Gem::Security for details. |
default_executable | [W] |
Sets the default executable for
this gem.
Deprecated: You must now specify the executable name to Gem.bin_path. |
description | [R] | A long description of this gem |
[RW] |
A contact email for this gem
If you are providing multiple authors and multiple emails they should be in the same order such that: Hash[*spec.authors.zip(spec.emails).flatten] Gives a hash of author name to email address. |
|
homepage | [RW] | The URL of this gem‘s home page |
loaded_from | [R] | Path this gemspec was loaded from. This attribute is not persisted. |
post_install_message | [RW] | A message that gets displayed after the gem is installed |
required_ruby_version | [R] | The version of ruby required by this gem |
required_rubygems_version | [R] | The RubyGems version required by this gem |
rubyforge_project | [RW] | The rubyforge project this gem lives under. i.e. RubyGems’ rubyforge_project is "rubygems". |
signing_key | [RW] | The key used to sign this gem. See Gem::Security for details. |
Load custom marshal format, re-initializing defaults as needed
# File lib/rubygems/specification.rb, line 651 651: def self._load(str) 652: array = Marshal.load str 653: 654: spec = Gem::Specification.new 655: spec.instance_variable_set :@specification_version, array[1] 656: 657: current_version = CURRENT_SPECIFICATION_VERSION 658: 659: field_count = if spec.specification_version > current_version then 660: spec.instance_variable_set :@specification_version, 661: current_version 662: MARSHAL_FIELDS[current_version] 663: else 664: MARSHAL_FIELDS[spec.specification_version] 665: end 666: 667: if array.size < field_count then 668: raise TypeError, "invalid Gem::Specification format #{array.inspect}" 669: end 670: 671: # Cleanup any YAML::PrivateType. They only show up for an old bug 672: # where nil => null, so just convert them to nil based on the type. 673: 674: array.map! { |e| e.kind_of?(YAML::PrivateType) ? nil : e } 675: 676: spec.instance_variable_set :@rubygems_version, array[0] 677: # spec version 678: spec.instance_variable_set :@name, array[2] 679: spec.instance_variable_set :@version, array[3] 680: spec.date = array[4] 681: spec.instance_variable_set :@summary, array[5] 682: spec.instance_variable_set :@required_ruby_version, array[6] 683: spec.instance_variable_set :@required_rubygems_version, array[7] 684: spec.instance_variable_set :@original_platform, array[8] 685: spec.instance_variable_set :@dependencies, array[9] 686: spec.instance_variable_set :@rubyforge_project, array[10] 687: spec.instance_variable_set :@email, array[11] 688: spec.instance_variable_set :@authors, array[12] 689: spec.instance_variable_set :@description, array[13] 690: spec.instance_variable_set :@homepage, array[14] 691: spec.instance_variable_set :@has_rdoc, array[15] 692: spec.instance_variable_set :@new_platform, array[16] 693: spec.instance_variable_set :@platform, array[16].to_s 694: spec.instance_variable_set :@license, array[17] 695: spec.instance_variable_set :@loaded, false 696: spec.instance_variable_set :@activated, false 697: 698: spec 699: end
Adds spec to the known specifications, keeping the collection properly sorted.
# File lib/rubygems/specification.rb, line 297 297: def self.add_spec spec 298: # TODO: find all extraneous adds 299: # puts 300: # p :add_spec => [spec.full_name, caller.reject { |s| s =~ /minitest/ }] 301: 302: # TODO: flush the rest of the crap from the tests 303: # raise "no dupes #{spec.full_name} in #{all_names.inspect}" if 304: # _all.include? spec 305: 306: raise "nil spec!" unless spec # TODO: remove once we're happy with tests 307: 308: return if _all.include? spec 309: 310: _all << spec 311: _resort! 312: end
Adds multiple specs to the known specifications.
# File lib/rubygems/specification.rb, line 317 317: def self.add_specs *specs 318: raise "nil spec!" if specs.any?(&:nil?) # TODO: remove once we're happy 319: 320: # TODO: this is much more efficient, but we need the extra checks for now 321: # _all.concat specs 322: # _resort! 323: 324: specs.each do |spec| # TODO: slow 325: add_spec spec 326: end 327: end
Returns all specifications. This method is discouraged from use. You probably want to use one of the Enumerable methods instead.
# File lib/rubygems/specification.rb, line 333 333: def self.all 334: warn "NOTE: Specification.all called from #{caller.first}" unless 335: Gem::Deprecate.skip 336: _all 337: end
Sets the known specs to specs. Not guaranteed to work for you in the future. Use at your own risk. Caveat emptor. Doomy doom doom. Etc etc.
# File lib/rubygems/specification.rb, line 351 351: def self.all= specs 352: @@all = specs 353: end
Return the directories that Specification uses to find specs.
# File lib/rubygems/specification.rb, line 383 383: def self.dirs 384: @@dirs ||= Gem.path.collect { |dir| 385: File.join dir, "specifications" 386: } 387: end
Set the directories that Specification uses to find specs. Setting this resets the list of known specs.
# File lib/rubygems/specification.rb, line 393 393: def self.dirs= dirs 394: # TODO: find extra calls to dir= 395: # warn "NOTE: dirs= called from #{caller.first} for #{dirs.inspect}" 396: 397: self.reset 398: 399: # ugh 400: @@dirs = Array(dirs).map { |dir| File.join dir, "specifications" } 401: end
Returns every spec that matches name and optional requirements.
# File lib/rubygems/specification.rb, line 420 420: def self.find_all_by_name name, *requirements 421: requirements = Gem::Requirement.default if requirements.empty? 422: 423: # TODO: maybe try: find_all { |s| spec === dep } 424: 425: Gem::Dependency.new(name, *requirements).matching_specs 426: end
Find the best specification matching a name and requirements. Raises if the dependency doesn‘t resolve to a valid specification.
# File lib/rubygems/specification.rb, line 432 432: def self.find_by_name name, *requirements 433: requirements = Gem::Requirement.default if requirements.empty? 434: 435: # TODO: maybe try: find { |s| spec === dep } 436: 437: Gem::Dependency.new(name, *requirements).to_spec 438: end
Return the best specification that contains the file matching path.
# File lib/rubygems/specification.rb, line 443 443: def self.find_by_path path 444: self.find { |spec| 445: spec.contains_requirable_file? path 446: } 447: end
Return currently unresolved specs that contain the file matching path.
# File lib/rubygems/specification.rb, line 452 452: def self.find_in_unresolved path 453: # TODO: do we need these?? Kill it 454: specs = Gem.unresolved_deps.values.map { |dep| dep.to_specs }.flatten 455: 456: specs.find_all { |spec| spec.contains_requirable_file? path } 457: end
Search through all unresolved deps and sub-dependencies and return specs that contain the file matching path.
# File lib/rubygems/specification.rb, line 463 463: def self.find_in_unresolved_tree path 464: specs = Gem.unresolved_deps.values.map { |dep| dep.to_specs }.flatten 465: 466: specs.reverse_each do |spec| 467: trails = [] 468: spec.traverse do |from_spec, dep, to_spec, trail| 469: next unless to_spec.conflicts.empty? 470: trails << trail if to_spec.contains_requirable_file? path 471: end 472: 473: next if trails.empty? 474: 475: return trails.map(&:reverse).sort.first.reverse 476: end 477: 478: [] 479: end
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.
# File lib/rubygems/specification.rb, line 489 489: def self.from_yaml(input) 490: Gem.load_yaml 491: 492: input = normalize_yaml_input input 493: spec = YAML.load input 494: 495: if spec && spec.class == FalseClass then 496: raise Gem::EndOfYAMLException 497: end 498: 499: unless Gem::Specification === spec then 500: raise Gem::Exception, "YAML data doesn't evaluate to gem specification" 501: end 502: 503: unless (spec.instance_variables.include? '@specification_version' or 504: spec.instance_variables.include? :@specification_version) and 505: spec.instance_variable_get :@specification_version 506: spec.instance_variable_set :@specification_version, 507: NONEXISTENT_SPECIFICATION_VERSION 508: end 509: 510: spec 511: end
Return the latest specs, optionally including prerelease specs if prerelease is true.
# File lib/rubygems/specification.rb, line 517 517: def self.latest_specs prerelease = false 518: result = Hash.new { |h,k| h[k] = {} } 519: native = {} 520: 521: Gem::Specification._all.reverse_each do |spec| 522: next if spec.version.prerelease? unless prerelease 523: 524: native[spec.name] = spec.version if spec.platform == Gem::Platform::RUBY 525: result[spec.name][spec.platform] = spec 526: end 527: 528: result.map(&:last).map(&:values).flatten.reject { |spec| 529: minimum = native[spec.name] 530: minimum && spec.version < minimum 531: } 532: end
Loads Ruby format gemspec from file.
# File lib/rubygems/specification.rb, line 537 537: def self.load file 538: return unless file && File.file?(file) 539: 540: file = file.dup.untaint 541: 542: code = if defined? Encoding 543: File.read file, :mode => 'r:UTF-8:-' 544: else 545: File.read file 546: end 547: 548: code.untaint 549: 550: begin 551: spec = eval code, binding, file 552: 553: if Gem::Specification === spec 554: spec.loaded_from = file.to_s 555: return spec 556: end 557: 558: warn "[#{file}] isn't a Gem::Specification (#{spec.class} instead)." 559: rescue SignalException, SystemExit 560: raise 561: rescue SyntaxError, Exception => e 562: warn "Invalid gemspec in [#{file}]: #{e}" 563: end 564: 565: nil 566: end
Specification constructor. Assigns the default values to the attributes and yields itself for further initialization. Optionally takes name and version.
# File lib/rubygems/specification.rb, line 1345 1345: def initialize name = nil, version = nil 1346: @loaded = false 1347: @activated = false 1348: @loaded_from = nil 1349: @original_platform = nil 1350: 1351: @@nil_attributes.each do |key| 1352: instance_variable_set "@#{key}", nil 1353: end 1354: 1355: @@non_nil_attributes.each do |key| 1356: default = default_value(key) 1357: value = case default 1358: when Time, Numeric, Symbol, true, false, nil then default 1359: else default.dup 1360: end 1361: 1362: instance_variable_set "@#{key}", value 1363: end 1364: 1365: @new_platform = Gem::Platform::RUBY 1366: 1367: self.name = name if name 1368: self.version = version if version 1369: 1370: yield self if block_given? 1371: end
Specification attributes that must be non-nil
# File lib/rubygems/specification.rb, line 571 571: def self.non_nil_attributes 572: @@non_nil_attributes.dup 573: end
Make sure the YAML specification is properly formatted with dashes
# File lib/rubygems/specification.rb, line 578 578: def self.normalize_yaml_input(input) 579: result = input.respond_to?(:read) ? input.read : input 580: result = "--- " + result unless result =~ /\A--- / 581: result.gsub!(/ !!null \n/, " \n") 582: # date: 2011-04-26 00:00:00.000000000Z 583: # date: 2011-04-26 00:00:00.000000000 Z 584: result.gsub!(/^(date: \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+?)Z/, '\1 Z') 585: result 586: end
Return a list of all outdated specifications. This method is HEAVY as it must go fetch specifications from the server.
# File lib/rubygems/specification.rb, line 592 592: def self.outdated 593: outdateds = [] 594: 595: # TODO: maybe we should switch to rubygems' version service? 596: fetcher = Gem::SpecFetcher.fetcher 597: 598: latest_specs.each do |local| 599: dependency = Gem::Dependency.new local.name, ">= #{local.version}" 600: remotes = fetcher.find_matching dependency 601: remotes = remotes.map { |(_, version, _), _| version } 602: latest = remotes.sort.last 603: 604: outdateds << local.name if latest and local.version < latest 605: end 606: 607: outdateds 608: end
Removes spec from the known specs.
# File lib/rubygems/specification.rb, line 613 613: def self.remove_spec spec 614: # TODO: beat on the tests 615: raise "wtf: #{spec.full_name} not in #{all_names.inspect}" unless 616: _all.include? spec 617: _all.delete spec 618: end
Is name a required attribute?
# File lib/rubygems/specification.rb, line 623 623: def self.required_attribute?(name) 624: @@required_attributes.include? name.to_sym 625: end
Required specification attributes
# File lib/rubygems/specification.rb, line 630 630: def self.required_attributes 631: @@required_attributes.dup 632: end
Reset the list of known specs, running pre and post reset hooks registered in Gem.
# File lib/rubygems/specification.rb, line 638 638: def self.reset 639: @@dirs = nil 640: # from = caller.first(10).reject { |s| s =~ /minitest/ } 641: # warn "" 642: # warn "NOTE: Specification.reset from #{from.inspect}" 643: Gem.pre_reset_hooks.each { |hook| hook.call } 644: @@all = nil 645: Gem.post_reset_hooks.each { |hook| hook.call } 646: end
Dump only crucial instance variables.
# File lib/rubygems/specification.rb, line 718 718: def _dump(limit) 719: Marshal.dump [ 720: @rubygems_version, 721: @specification_version, 722: @name, 723: @version, 724: date, 725: @summary, 726: @required_ruby_version, 727: @required_rubygems_version, 728: @original_platform, 729: @dependencies, 730: @rubyforge_project, 731: @email, 732: @authors, 733: @description, 734: @homepage, 735: true, # has_rdoc 736: @new_platform, 737: @licenses 738: ] 739: end
Activate this spec, registering it as a loaded spec and adding it‘s lib paths to $LOAD_PATH. Returns true if the spec was activated, false if it was previously activated. Freaks out if there are conflicts upon activation.
# File lib/rubygems/specification.rb, line 747 747: def activate 748: raise_if_conflicts 749: 750: return false if Gem.loaded_specs[self.name] 751: 752: activate_dependencies 753: add_self_to_load_path 754: 755: Gem.loaded_specs[self.name] = self 756: @activated = true 757: @loaded = true 758: 759: return true 760: end
Activate all unambiguously resolved runtime dependencies of this spec. Add any ambigous dependencies to the unresolved list to be resolved later, as needed.
# File lib/rubygems/specification.rb, line 767 767: def activate_dependencies 768: self.runtime_dependencies.each do |spec_dep| 769: if loaded = Gem.loaded_specs[spec_dep.name] 770: next if spec_dep.matches_spec? loaded 771: 772: msg = "can't satisfy '#{spec_dep}', already activated '#{loaded.full_name}'" 773: e = Gem::LoadError.new msg 774: e.name = spec_dep.name 775: 776: raise e 777: end 778: 779: specs = spec_dep.to_specs 780: 781: if specs.size == 1 then 782: specs.first.activate 783: else 784: name = spec_dep.name 785: Gem.unresolved_deps[name] = Gem.unresolved_deps[name].merge spec_dep 786: end 787: end 788: 789: Gem.unresolved_deps.delete self.name 790: end
Returns an array with bindir attached to each executable in the executables list
# File lib/rubygems/specification.rb, line 796 796: def add_bindir(executables) 797: return nil if executables.nil? 798: 799: if @bindir then 800: Array(executables).map { |e| File.join(@bindir, e) } 801: else 802: executables 803: end 804: rescue 805: return nil 806: end
Adds a development dependency named gem with requirements to this Gem. For example:
spec.add_development_dependency 'example', '~> 1.1', '>= 1.1.4'
Development dependencies aren‘t installed by default and aren‘t activated when a gem is required.
# File lib/rubygems/specification.rb, line 840 840: def add_development_dependency(gem, *requirements) 841: add_dependency_with_type(gem, :development, *requirements) 842: end
Adds a runtime dependency named gem with requirements to this Gem. For example:
spec.add_runtime_dependency 'example', '~> 1.1', '>= 1.1.4'
# File lib/rubygems/specification.rb, line 850 850: def add_runtime_dependency(gem, *requirements) 851: add_dependency_with_type(gem, :runtime, *requirements) 852: end
Adds this spec‘s require paths to LOAD_PATH, in the proper location.
# File lib/rubygems/specification.rb, line 859 859: def add_self_to_load_path 860: paths = require_paths.map do |path| 861: File.join full_gem_path, path 862: end 863: 864: # gem directories must come after -I and ENV['RUBYLIB'] 865: insert_index = Gem.load_path_insert_index 866: 867: if insert_index then 868: # gem directories must come after -I and ENV['RUBYLIB'] 869: $LOAD_PATH.insert(insert_index, *paths) 870: else 871: # we are probably testing in core, -I and RUBYLIB don't apply 872: $LOAD_PATH.unshift(*paths) 873: end 874: end
The list of author names who wrote this gem.
If you are providing multiple authors and multiple emails they should be in the same order such that:
Hash[*spec.authors.zip(spec.emails).flatten]
Gives a hash of author name to email address.
# File lib/rubygems/specification.rb, line 900 900: def authors 901: @authors ||= [] 902: end
Returns the full path to the base gem directory.
eg: /usr/local/lib/ruby/gems/1.8
# File lib/rubygems/specification.rb, line 916 916: def base_dir 917: return Gem.dir unless loaded_from 918: @base_dir ||= File.dirname File.dirname loaded_from 919: end
Returns the full path to installed gem‘s bin directory.
NOTE: do not confuse this with bindir, which is just ‘bin’, not a full path.
# File lib/rubygems/specification.rb, line 927 927: def bin_dir 928: @bin_dir ||= File.join gem_dir, bindir # TODO: this is unfortunate 929: end
Returns the full path to an executable named name in this gem.
# File lib/rubygems/specification.rb, line 934 934: def bin_file name 935: File.join bin_dir, name 936: end
Returns the full path to the cache directory containing this spec‘s cached gem.
# File lib/rubygems/specification.rb, line 942 942: def cache_dir 943: @cache_dir ||= File.join base_dir, "cache" 944: end
Returns the full path to the cached gem for this spec.
# File lib/rubygems/specification.rb, line 949 949: def cache_file 950: @cache_file ||= File.join cache_dir, "#{full_name}.gem" 951: end
Return any possible conflicts against the currently loaded specs.
# File lib/rubygems/specification.rb, line 958 958: def conflicts 959: conflicts = {} 960: Gem.loaded_specs.values.each do |spec| 961: bad = self.runtime_dependencies.find_all { |dep| 962: spec.name == dep.name and not spec.satisfies_requirement? dep 963: } 964: 965: conflicts[spec] = bad unless bad.empty? 966: end 967: conflicts 968: end
Return true if this spec can require file.
# File lib/rubygems/specification.rb, line 973 973: def contains_requirable_file? file 974: root = full_gem_path 975: 976: require_paths.each do |lib| 977: base = "#{root}/#{lib}/#{file}" 978: Gem.suffixes.each do |suf| 979: path = "#{base}#{suf}" 980: return true if File.file? path 981: end 982: end 983: 984: return false 985: end
The date this gem was created
Do not set this, it is set automatically when the gem is packaged.
# File lib/rubygems/specification.rb, line 999 999: def date= date 1000: # We want to end up with a Time object with one-day resolution. 1001: # This is the cleanest, most-readable, faster-than-using-Date 1002: # way to do it. 1003: @date = case date 1004: when String then 1005: if /\A(\d{4})-(\d{2})-(\d{2})\Z/ =~ date then 1006: Time.utc($1.to_i, $2.to_i, $3.to_i) 1007: 1008: # Workaround for where the date format output from psych isn't 1009: # parsed as a Time object by syck and thus comes through as a 1010: # string. 1011: elsif /\A(\d{4})-(\d{2})-(\d{2}) \d{2}:\d{2}:\d{2}\.\d+?Z\z/ =~ date then 1012: Time.utc($1.to_i, $2.to_i, $3.to_i) 1013: else 1014: raise(Gem::InvalidSpecificationException, 1015: "invalid date format in specification: #{date.inspect}") 1016: end 1017: when Time, Date then 1018: Time.utc(date.year, date.month, date.day) 1019: else 1020: TODAY 1021: end 1022: end
The default executable for this gem.
Deprecated: The name of the gem is assumed to be the name of the executable now. See Gem.bin_path.
# File lib/rubygems/specification.rb, line 1030 1030: def default_executable 1031: if defined?(@default_executable) and @default_executable 1032: result = @default_executable 1033: elsif @executables and @executables.size == 1 1034: result = Array(@executables).first 1035: else 1036: result = nil 1037: end 1038: result 1039: end
The default value for specification attribute name
# File lib/rubygems/specification.rb, line 1044 1044: def default_value name 1045: @@default_value[name] 1046: end
A list of Gem::Dependency objects this gem depends on.
Use add_dependency or add_development_dependency to add dependencies to a gem.
# File lib/rubygems/specification.rb, line 1054 1054: def dependencies 1055: @dependencies ||= [] 1056: end
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]]
# File lib/rubygems/specification.rb, line 1064 1064: def dependent_gems 1065: out = [] 1066: Gem::Specification.each do |spec| 1067: spec.dependencies.each do |dep| 1068: if self.satisfies_requirement?(dep) then 1069: sats = [] 1070: find_all_satisfiers(dep) do |sat| 1071: sats << sat 1072: end 1073: out << [spec, dep, sats] 1074: end 1075: end 1076: end 1077: out 1078: end
Returns all specs that matches this spec‘s runtime dependencies.
# File lib/rubygems/specification.rb, line 1083 1083: def dependent_specs 1084: runtime_dependencies.map { |dep| dep.to_specs }.flatten 1085: end
A long description of this gem
# File lib/rubygems/specification.rb, line 1090 1090: def description= str 1091: @description = str.to_s 1092: end
List of dependencies that are used for development
# File lib/rubygems/specification.rb, line 1097 1097: def development_dependencies 1098: dependencies.select { |d| d.type == :development } 1099: end
Returns the full path to this spec‘s documentation directory.
# File lib/rubygems/specification.rb, line 1104 1104: def doc_dir 1105: @doc_dir ||= File.join base_dir, 'doc', full_name 1106: end
Singular accessor for executables
# File lib/rubygems/specification.rb, line 1136 1136: def executable 1137: val = executables and val.first 1138: end
Singular accessor for executables
# File lib/rubygems/specification.rb, line 1143 1143: def executable=o 1144: self.executables = [o] 1145: end
Executables included in the gem.
# File lib/rubygems/specification.rb, line 1150 1150: def executables 1151: @executables ||= [] 1152: end
Sets executables to value, ensuring it is an array. Don‘t use this, push onto the array instead.
# File lib/rubygems/specification.rb, line 1158 1158: def executables= value 1159: # TODO: warn about setting instead of pushing 1160: @executables = Array(value) 1161: end
Extensions to build when installing the gem. See Gem::Installer#build_extensions for valid values.
# File lib/rubygems/specification.rb, line 1167 1167: def extensions 1168: @extensions ||= [] 1169: end
Sets extensions to extensions, ensuring it is an array. Don‘t use this, push onto the array instead.
# File lib/rubygems/specification.rb, line 1175 1175: def extensions= extensions 1176: # TODO: warn about setting instead of pushing 1177: @extensions = Array extensions 1178: end
Sets extra_rdoc_files to files, ensuring it is an array. Don‘t use this, push onto the array instead.
# File lib/rubygems/specification.rb, line 1191 1191: def extra_rdoc_files= files 1192: # TODO: warn about setting instead of pushing 1193: @extra_rdoc_files = Array files 1194: end
Files included in this gem. You cannot append to this accessor, you must assign to it.
Only add files you can require to this list, not directories, etc.
Directories are automatically stripped from this list when building a gem, other non-files cause an error.
# File lib/rubygems/specification.rb, line 1214 1214: def files 1215: # DO NOT CHANGE TO ||= ! This is not a normal accessor. (yes, it sucks) 1216: @files = [@files, 1217: @test_files, 1218: add_bindir(@executables), 1219: @extra_rdoc_files, 1220: @extensions, 1221: ].flatten.uniq.compact 1222: end
Creates a duplicate spec without large blobs that aren‘t used at runtime.
# File lib/rubygems/specification.rb, line 1245 1245: def for_cache 1246: spec = dup 1247: 1248: spec.files = nil 1249: spec.test_files = nil 1250: 1251: spec 1252: end
The full path to the gem (install path + full name).
# File lib/rubygems/specification.rb, line 1257 1257: def full_gem_path 1258: # TODO: try to get rid of this... or the awkward 1259: # TODO: also, shouldn't it default to full_name if it hasn't been written? 1260: return @full_gem_path if defined?(@full_gem_path) && @full_gem_path 1261: 1262: @full_gem_path = File.expand_path File.join(gems_dir, full_name) 1263: 1264: return @full_gem_path if File.directory? @full_gem_path 1265: 1266: @full_gem_path = File.expand_path File.join(gems_dir, original_name) 1267: end
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.
# File lib/rubygems/specification.rb, line 1274 1274: def full_name 1275: if platform == Gem::Platform::RUBY or platform.nil? then 1276: "#{@name}-#{@version}" 1277: else 1278: "#{@name}-#{@version}-#{platform}" 1279: end 1280: end
Returns the full path to this spec‘s gem directory. eg: /usr/local/lib/ruby/1.8/gems/mygem-1.0
# File lib/rubygems/specification.rb, line 1286 1286: def gem_dir 1287: @gem_dir ||= File.expand_path File.join(gems_dir, full_name) 1288: end
Returns the full path to the gems directory containing this spec‘s gem directory. eg: /usr/local/lib/ruby/1.8/gems
# File lib/rubygems/specification.rb, line 1294 1294: def gems_dir 1295: # TODO: this logic seems terribly broken, but tests fail if just base_dir 1296: @gems_dir ||= File.join(loaded_from && base_dir || Gem.dir, "gems") 1297: end
Deprecated and ignored, defaults to true.
Formerly used to indicate this gem was RDoc-capable.
# File lib/rubygems/specification.rb, line 1304 1304: def has_rdoc 1305: true 1306: end
Deprecated and ignored.
Formerly used to indicate this gem was RDoc-capable.
# File lib/rubygems/specification.rb, line 1313 1313: def has_rdoc= ignored 1314: @has_rdoc = true 1315: end
True if this gem has files in test_files
# File lib/rubygems/specification.rb, line 1322 1322: def has_unit_tests? 1323: not test_files.empty? 1324: end
Duplicates array_attributes from other_spec so state isn‘t shared.
# File lib/rubygems/specification.rb, line 1376 1376: def initialize_copy other_spec 1377: other_ivars = other_spec.instance_variables 1378: other_ivars = other_ivars.map { |ivar| ivar.intern } if # for 1.9 1379: String === other_ivars.first 1380: 1381: self.class.array_attributes.each do |name| 1382: name = "@#{name}""@#{name}" 1383: next unless other_ivars.include? name 1384: 1385: begin 1386: val = other_spec.instance_variable_get(name) 1387: if val then 1388: instance_variable_set name, val.dup 1389: elsif Gem.configuration.really_verbose 1390: warn "WARNING: #{full_name} has an invalid nil value for #{name}" 1391: end 1392: rescue TypeError 1393: e = Gem::FormatException.new \ 1394: "#{full_name} has an invalid value for #{name}" 1395: 1396: e.file_path = loaded_from 1397: raise e 1398: end 1399: end 1400: end
Returns a string usable in Dir.glob to match all requirable paths for this spec.
# File lib/rubygems/specification.rb, line 1414 1414: def lib_dirs_glob 1415: dirs = if self.require_paths.size > 1 then 1416: "{#{self.require_paths.join(',')}}" 1417: else 1418: self.require_paths.first 1419: end 1420: 1421: "#{self.full_gem_path}/#{dirs}" 1422: end
Set the location a Specification was loaded from. obj is converted to a String.
# File lib/rubygems/specification.rb, line 1468 1468: def loaded_from= path 1469: @loaded_from = path.to_s 1470: end
Sets the rubygems_version to the current RubyGems version.
# File lib/rubygems/specification.rb, line 1475 1475: def mark_version 1476: @rubygems_version = Gem::VERSION 1477: end
Return all files in this gem that match for glob.
# File lib/rubygems/specification.rb, line 1482 1482: def matches_for_glob glob # TODO: rename? 1483: # TODO: do we need these?? Kill it 1484: glob = File.join(self.lib_dirs_glob, glob) 1485: 1486: Dir[glob].map { |f| f.untaint } # FIX our tests are broken, run w/ SAFE=1 1487: end
Normalize the list of files so that:
# File lib/rubygems/specification.rb, line 1507 1507: def normalize 1508: if defined?(@extra_rdoc_files) and @extra_rdoc_files then 1509: @extra_rdoc_files.uniq! 1510: @files ||= [] 1511: @files.concat(@extra_rdoc_files) 1512: end 1513: 1514: @files = @files.uniq if @files 1515: @extensions = @extensions.uniq if @extensions 1516: @test_files = @test_files.uniq if @test_files 1517: @executables = @executables.uniq if @executables 1518: @extra_rdoc_files = @extra_rdoc_files.uniq if @extra_rdoc_files 1519: end
The platform this gem runs on. See Gem::Platform for details.
# File lib/rubygems/specification.rb, line 1543 1543: def platform 1544: @new_platform ||= Gem::Platform::RUBY 1545: end
The platform this gem runs on. See Gem::Platform for details.
Setting this to any value other than Gem::Platform::RUBY or Gem::Platform::CURRENT is probably wrong.
# File lib/rubygems/specification.rb, line 1553 1553: def platform= platform 1554: if @original_platform.nil? or 1555: @original_platform == Gem::Platform::RUBY then 1556: @original_platform = platform 1557: end 1558: 1559: case platform 1560: when Gem::Platform::CURRENT then 1561: @new_platform = Gem::Platform.local 1562: @original_platform = @new_platform.to_s 1563: 1564: when Gem::Platform then 1565: @new_platform = platform 1566: 1567: # legacy constants 1568: when nil, Gem::Platform::RUBY then 1569: @new_platform = Gem::Platform::RUBY 1570: when 'mswin32' then # was Gem::Platform::WIN32 1571: @new_platform = Gem::Platform.new 'x86-mswin32' 1572: when 'i586-linux' then # was Gem::Platform::LINUX_586 1573: @new_platform = Gem::Platform.new 'x86-linux' 1574: when 'powerpc-darwin' then # was Gem::Platform::DARWIN 1575: @new_platform = Gem::Platform.new 'ppc-darwin' 1576: else 1577: @new_platform = Gem::Platform.new platform 1578: end 1579: 1580: @platform = @new_platform.to_s 1581: 1582: @new_platform 1583: end
Check the spec for possible conflicts and freak out if there are any.
# File lib/rubygems/specification.rb, line 1614 1614: def raise_if_conflicts 1615: other = Gem.loaded_specs[self.name] 1616: 1617: if other and self.version != other.version then 1618: # This gem is already loaded. If the currently loaded gem is not in the 1619: # list of candidate gems, then we have a version conflict. 1620: 1621: msg = "can't activate #{full_name}, already activated #{other.full_name}" 1622: 1623: e = Gem::LoadError.new msg 1624: e.name = self.name 1625: # TODO: e.requirement = dep.requirement 1626: 1627: raise e 1628: end 1629: 1630: conf = self.conflicts 1631: 1632: unless conf.empty? then 1633: y = conf.map { |act,con| 1634: "#{act.full_name} conflicts with #{con.join(", ")}" 1635: }.join ", " 1636: 1637: # TODO: improve message by saying who activated `con` 1638: 1639: raise Gem::LoadError, "Unable to activate #{self.full_name}, because #{y}" 1640: end 1641: end
An ARGV style array of options to RDoc
# File lib/rubygems/specification.rb, line 1646 1646: def rdoc_options 1647: @rdoc_options ||= [] 1648: end
Sets rdoc_options to value, ensuring it is an array. Don‘t use this, push onto the array instead.
# File lib/rubygems/specification.rb, line 1654 1654: def rdoc_options= options 1655: # TODO: warn about setting instead of pushing 1656: @rdoc_options = Array options 1657: end
Singular accessor for require_paths
# File lib/rubygems/specification.rb, line 1662 1662: def require_path 1663: val = require_paths and val.first 1664: end
Singular accessor for require_paths
# File lib/rubygems/specification.rb, line 1669 1669: def require_path= path 1670: self.require_paths = [path] 1671: end
The version of ruby required by this gem
# File lib/rubygems/specification.rb, line 1676 1676: def required_ruby_version= req 1677: @required_ruby_version = Gem::Requirement.create req 1678: end
The RubyGems version required by this gem
# File lib/rubygems/specification.rb, line 1683 1683: def required_rubygems_version= req 1684: @required_rubygems_version = Gem::Requirement.create req 1685: end
An array or things required by this gem. Not used by anything presently.
# File lib/rubygems/specification.rb, line 1691 1691: def requirements 1692: @requirements ||= [] 1693: end
Set requirements to req, ensuring it is an array. Don‘t use this, push onto the array instead.
# File lib/rubygems/specification.rb, line 1699 1699: def requirements= req 1700: # TODO: warn about setting instead of pushing 1701: @requirements = Array req 1702: end
Returns the full path to this spec‘s ri directory.
# File lib/rubygems/specification.rb, line 1707 1707: def ri_dir 1708: @ri_dir ||= File.join base_dir, 'ri', full_name 1709: end
List of dependencies that will automatically be activated at runtime.
# File lib/rubygems/specification.rb, line 1735 1735: def runtime_dependencies 1736: dependencies.select { |d| d.type == :runtime } 1737: end
Checks if this specification meets the requirement of dependency.
# File lib/rubygems/specification.rb, line 1751 1751: def satisfies_requirement? dependency 1752: return @name == dependency.name && 1753: dependency.requirement.satisfied_by?(@version) 1754: end
Returns an object you can use to sort specifications in sort_by.
# File lib/rubygems/specification.rb, line 1759 1759: def sort_obj 1760: # TODO: this is horrible. Deprecate it. 1761: [@name, @version, @new_platform == Gem::Platform::RUBY ? -1 : 1] 1762: end
Returns the full path to the directory containing this spec‘s gemspec file. eg: /usr/local/lib/ruby/gems/1.8/specifications
# File lib/rubygems/specification.rb, line 1768 1768: def spec_dir 1769: @spec_dir ||= File.join base_dir, "specifications" 1770: end
Returns the full path to this spec‘s gemspec file. eg: /usr/local/lib/ruby/gems/1.8/specifications/mygem-1.0.gemspec
# File lib/rubygems/specification.rb, line 1776 1776: def spec_file 1777: @spec_file ||= File.join spec_dir, "#{full_name}.gemspec" 1778: end
A short summary of this gem‘s description.
# File lib/rubygems/specification.rb, line 1792 1792: def summary= str 1793: @summary = str.to_s.strip. 1794: gsub(/(\w-)\n[ \t]*(\w)/, '\1\2').gsub(/\n[ \t]*/, " ") # so. weird. 1795: end
Singular accessor for test_files
# File lib/rubygems/specification.rb, line 1800 1800: def test_file 1801: val = test_files and val.first 1802: end
Singular accessor for test_files
# File lib/rubygems/specification.rb, line 1807 1807: def test_file= file 1808: self.test_files = [file] 1809: end
Test files included in this gem. You cannot append to this accessor, you must assign to it.
# File lib/rubygems/specification.rb, line 1815 1815: def test_files 1816: # Handle the possibility that we have @test_suite_file but not 1817: # @test_files. This will happen when an old gem is loaded via 1818: # YAML. 1819: if defined? @test_suite_file then 1820: @test_files = [@test_suite_file].flatten 1821: @test_suite_file = nil 1822: end 1823: if defined?(@test_files) and @test_files then 1824: @test_files 1825: else 1826: @test_files = [] 1827: end 1828: end
Set test_files to files, ensuring it is an array.
# File lib/rubygems/specification.rb, line 1833 1833: def test_files= files 1834: @test_files = Array files 1835: end
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.
# File lib/rubygems/specification.rb, line 1853 1853: def to_ruby 1854: mark_version 1855: result = [] 1856: result << "# -*- encoding: utf-8 -*-" 1857: result << nil 1858: result << "Gem::Specification.new do |s|" 1859: 1860: result << " s.name = #{ruby_code name}" 1861: result << " s.version = #{ruby_code version}" 1862: unless platform.nil? or platform == Gem::Platform::RUBY then 1863: result << " s.platform = #{ruby_code original_platform}" 1864: end 1865: result << "" 1866: result << " s.required_rubygems_version = #{ruby_code required_rubygems_version} if s.respond_to? :required_rubygems_version=" 1867: 1868: handled = [ 1869: :dependencies, 1870: :name, 1871: :platform, 1872: :required_rubygems_version, 1873: :specification_version, 1874: :version, 1875: :has_rdoc, 1876: :default_executable, 1877: ] 1878: 1879: @@attributes.each do |attr_name| 1880: next if handled.include? attr_name 1881: current_value = self.send(attr_name) 1882: if current_value != default_value(attr_name) or 1883: self.class.required_attribute? attr_name then 1884: result << " s.#{attr_name} = #{ruby_code current_value}" 1885: end 1886: end 1887: 1888: result << nil 1889: result << " if s.respond_to? :specification_version then" 1890: result << " s.specification_version = #{specification_version}" 1891: result << nil 1892: 1893: result << " if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then" 1894: 1895: dependencies.each do |dep| 1896: req = dep.requirements_list.inspect 1897: dep.instance_variable_set :@type, :runtime if dep.type.nil? # HACK 1898: result << " s.add_#{dep.type}_dependency(%q<#{dep.name}>, #{req})" 1899: end 1900: 1901: result << " else" 1902: 1903: dependencies.each do |dep| 1904: version_reqs_param = dep.requirements_list.inspect 1905: result << " s.add_dependency(%q<#{dep.name}>, #{version_reqs_param})" 1906: end 1907: 1908: result << ' end' 1909: 1910: result << " else" 1911: dependencies.each do |dep| 1912: version_reqs_param = dep.requirements_list.inspect 1913: result << " s.add_dependency(%q<#{dep.name}>, #{version_reqs_param})" 1914: end 1915: result << " end" 1916: 1917: result << "end" 1918: result << nil 1919: 1920: result.join "\n" 1921: end
Recursively walk dependencies of this spec, executing the block for each hop.
# File lib/rubygems/specification.rb, line 1968 1968: def traverse trail = [], &block 1969: trail = trail + [self] 1970: runtime_dependencies.each do |dep| 1971: dep.to_specs.each do |dep_spec| 1972: block[self, dep, dep_spec, trail + [dep_spec]] 1973: dep_spec.traverse(trail, &block) unless 1974: trail.map(&:name).include? dep_spec.name 1975: end 1976: end 1977: end
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..
# File lib/rubygems/specification.rb, line 1986 1986: def validate packaging = true 1987: require 'rubygems/user_interaction' 1988: extend Gem::UserInteraction 1989: normalize 1990: 1991: nil_attributes = self.class.non_nil_attributes.find_all do |name| 1992: instance_variable_get("@#{name}").nil? 1993: end 1994: 1995: unless nil_attributes.empty? then 1996: raise Gem::InvalidSpecificationException, 1997: "#{nil_attributes.join ', '} must not be nil" 1998: end 1999: 2000: if packaging and rubygems_version != Gem::VERSION then 2001: raise Gem::InvalidSpecificationException, 2002: "expected RubyGems version #{Gem::VERSION}, was #{rubygems_version}" 2003: end 2004: 2005: @@required_attributes.each do |symbol| 2006: unless self.send symbol then 2007: raise Gem::InvalidSpecificationException, 2008: "missing value for attribute #{symbol}" 2009: end 2010: end 2011: 2012: if !name.is_a?(String) then 2013: raise Gem::InvalidSpecificationException, 2014: "invalid value for attribute name: \"#{name.inspect}\" must be a string" 2015: elsif name !~ /[a-zA-Z]/ then 2016: raise Gem::InvalidSpecificationException, 2017: "invalid value for attribute name: #{name.dump} must include at least one letter" 2018: elsif name !~ VALID_NAME_PATTERN then 2019: raise Gem::InvalidSpecificationException, 2020: "invalid value for attribute name: #{name.dump} can only include letters, numbers, dashes, and underscores" 2021: end 2022: 2023: if require_paths.empty? then 2024: raise Gem::InvalidSpecificationException, 2025: 'specification must have at least one require_path' 2026: end 2027: 2028: @files.delete_if { |x| File.directory?(x) } 2029: @test_files.delete_if { |x| File.directory?(x) } 2030: @executables.delete_if { |x| File.directory?(File.join(@bindir, x)) } 2031: @extra_rdoc_files.delete_if { |x| File.directory?(x) } 2032: @extensions.delete_if { |x| File.directory?(x) } 2033: 2034: non_files = files.reject { |x| File.file?(x) } 2035: 2036: unless not packaging or non_files.empty? then 2037: raise Gem::InvalidSpecificationException, 2038: "[\"#{non_files.join "\", \""}\"] are not files" 2039: end 2040: 2041: unless specification_version.is_a?(Fixnum) 2042: raise Gem::InvalidSpecificationException, 2043: 'specification_version must be a Fixnum (did you mean version?)' 2044: end 2045: 2046: case platform 2047: when Gem::Platform, Gem::Platform::RUBY then # ok 2048: else 2049: raise Gem::InvalidSpecificationException, 2050: "invalid platform #{platform.inspect}, see Gem::Platform" 2051: end 2052: 2053: self.class.array_attributes.each do |field| 2054: val = self.send field 2055: klass = case field 2056: when :dependencies 2057: Gem::Dependency 2058: else 2059: String 2060: end 2061: 2062: unless Array === val and val.all? { |x| x.kind_of?(klass) } then 2063: raise(Gem::InvalidSpecificationException, 2064: "#{field} must be an Array of #{klass}") 2065: end 2066: end 2067: 2068: [:authors].each do |field| 2069: val = self.send field 2070: raise Gem::InvalidSpecificationException, "#{field} may not be empty" if 2071: val.empty? 2072: end 2073: 2074: licenses.each { |license| 2075: if license.length > 64 2076: raise Gem::InvalidSpecificationException, 2077: "each license must be 64 characters or less" 2078: end 2079: } 2080: 2081: # reject lazy developers: 2082: 2083: lazy = '"FIxxxXME" or "TOxxxDO"'.gsub(/xxx/, '') 2084: 2085: unless authors.grep(/FI XME|TO DO/x).empty? then 2086: raise Gem::InvalidSpecificationException, "#{lazy} is not an author" 2087: end 2088: 2089: unless Array(email).grep(/FI XME|TO DO/x).empty? then 2090: raise Gem::InvalidSpecificationException, "#{lazy} is not an email" 2091: end 2092: 2093: if description =~ /FI XME|TO DO/x then 2094: raise Gem::InvalidSpecificationException, "#{lazy} is not a description" 2095: end 2096: 2097: if summary =~ /FI XME|TO DO/x then 2098: raise Gem::InvalidSpecificationException, "#{lazy} is not a summary" 2099: end 2100: 2101: if homepage and not homepage.empty? and 2102: homepage !~ /\A[a-z][a-z\d+.-]*:/i then 2103: raise Gem::InvalidSpecificationException, 2104: "\"#{homepage}\" is not a URI" 2105: end 2106: 2107: # Warnings 2108: 2109: %w[author description email homepage summary].each do |attribute| 2110: value = self.send attribute 2111: alert_warning "no #{attribute} specified" if value.nil? or value.empty? 2112: end 2113: 2114: if description == summary then 2115: alert_warning 'description and summary are identical' 2116: end 2117: 2118: # TODO: raise at some given date 2119: alert_warning "deprecated autorequire specified" if autorequire 2120: 2121: executables.each do |executable| 2122: executable_path = File.join(bindir, executable) 2123: shebang = File.read(executable_path, 2) == '#!' 2124: 2125: alert_warning "#{executable_path} is missing #! line" unless shebang 2126: end 2127: 2128: true 2129: end
Set the version to version, potentially also setting required_rubygems_version if version indicates it is a prerelease.
# File lib/rubygems/specification.rb, line 2136 2136: def version= version 2137: @version = Gem::Version.create(version) 2138: self.required_rubygems_version = '> 1.3.1' if @version.prerelease? 2139: return @version 2140: end