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