| 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 649
649: def self._load(str)
650: array = Marshal.load str
651:
652: spec = Gem::Specification.new
653: spec.instance_variable_set :@specification_version, array[1]
654:
655: current_version = CURRENT_SPECIFICATION_VERSION
656:
657: field_count = if spec.specification_version > current_version then
658: spec.instance_variable_set :@specification_version,
659: current_version
660: MARSHAL_FIELDS[current_version]
661: else
662: MARSHAL_FIELDS[spec.specification_version]
663: end
664:
665: if array.size < field_count then
666: raise TypeError, "invalid Gem::Specification format #{array.inspect}"
667: end
668:
669: # Cleanup any YAML::PrivateType. They only show up for an old bug
670: # where nil => null, so just convert them to nil based on the type.
671:
672: array.map! { |e| e.kind_of?(YAML::PrivateType) ? nil : e }
673:
674: spec.instance_variable_set :@rubygems_version, array[0]
675: # spec version
676: spec.instance_variable_set :@name, array[2]
677: spec.instance_variable_set :@version, array[3]
678: spec.date = array[4]
679: spec.instance_variable_set :@summary, array[5]
680: spec.instance_variable_set :@required_ruby_version, array[6]
681: spec.instance_variable_set :@required_rubygems_version, array[7]
682: spec.instance_variable_set :@original_platform, array[8]
683: spec.instance_variable_set :@dependencies, array[9]
684: spec.instance_variable_set :@rubyforge_project, array[10]
685: spec.instance_variable_set :@email, array[11]
686: spec.instance_variable_set :@authors, array[12]
687: spec.instance_variable_set :@description, array[13]
688: spec.instance_variable_set :@homepage, array[14]
689: spec.instance_variable_set :@has_rdoc, array[15]
690: spec.instance_variable_set :@new_platform, array[16]
691: spec.instance_variable_set :@platform, array[16].to_s
692: spec.instance_variable_set :@license, array[17]
693: spec.instance_variable_set :@loaded, false
694: spec.instance_variable_set :@activated, false
695:
696: spec
697: end
Adds spec to the known specifications, keeping the collection properly sorted.
# File lib/rubygems/specification.rb, line 295
295: def self.add_spec spec
296: # TODO: find all extraneous adds
297: # puts
298: # p :add_spec => [spec.full_name, caller.reject { |s| s =~ /minitest/ }]
299:
300: # TODO: flush the rest of the crap from the tests
301: # raise "no dupes #{spec.full_name} in #{all_names.inspect}" if
302: # _all.include? spec
303:
304: raise "nil spec!" unless spec # TODO: remove once we're happy with tests
305:
306: return if _all.include? spec
307:
308: _all << spec
309: _resort!
310: end
Adds multiple specs to the known specifications.
# File lib/rubygems/specification.rb, line 315
315: def self.add_specs *specs
316: raise "nil spec!" if specs.any?(&:nil?) # TODO: remove once we're happy
317:
318: # TODO: this is much more efficient, but we need the extra checks for now
319: # _all.concat specs
320: # _resort!
321:
322: specs.each do |spec| # TODO: slow
323: add_spec spec
324: end
325: 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 331
331: def self.all
332: warn "NOTE: Specification.all called from #{caller.first}" unless
333: Gem::Deprecate.skip
334: _all
335: 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 349
349: def self.all= specs
350: @@all = specs
351: end
Return the directories that Specification uses to find specs.
# File lib/rubygems/specification.rb, line 381
381: def self.dirs
382: @@dirs ||= Gem.path.collect { |dir|
383: File.join dir, "specifications"
384: }
385: end
Set the directories that Specification uses to find specs. Setting this resets the list of known specs.
# File lib/rubygems/specification.rb, line 391
391: def self.dirs= dirs
392: # TODO: find extra calls to dir=
393: # warn "NOTE: dirs= called from #{caller.first} for #{dirs.inspect}"
394:
395: self.reset
396:
397: # ugh
398: @@dirs = Array(dirs).map { |dir| File.join dir, "specifications" }
399: end
Returns every spec that matches name and optional requirements.
# File lib/rubygems/specification.rb, line 418
418: def self.find_all_by_name name, *requirements
419: requirements = Gem::Requirement.default if requirements.empty?
420:
421: # TODO: maybe try: find_all { |s| spec === dep }
422:
423: Gem::Dependency.new(name, *requirements).matching_specs
424: 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 430
430: def self.find_by_name name, *requirements
431: requirements = Gem::Requirement.default if requirements.empty?
432:
433: # TODO: maybe try: find { |s| spec === dep }
434:
435: Gem::Dependency.new(name, *requirements).to_spec
436: end
Return the best specification that contains the file matching path.
# File lib/rubygems/specification.rb, line 441
441: def self.find_by_path path
442: self.find { |spec|
443: spec.contains_requirable_file? path
444: }
445: end
Return currently unresolved specs that contain the file matching path.
# File lib/rubygems/specification.rb, line 450
450: def self.find_in_unresolved path
451: # TODO: do we need these?? Kill it
452: specs = Gem.unresolved_deps.values.map { |dep| dep.to_specs }.flatten
453:
454: specs.find_all { |spec| spec.contains_requirable_file? path }
455: end
Search through all unresolved deps and sub-dependencies and return specs that contain the file matching path.
# File lib/rubygems/specification.rb, line 461
461: def self.find_in_unresolved_tree path
462: specs = Gem.unresolved_deps.values.map { |dep| dep.to_specs }.flatten
463:
464: specs.reverse_each do |spec|
465: trails = []
466: spec.traverse do |from_spec, dep, to_spec, trail|
467: next unless to_spec.conflicts.empty?
468: trails << trail if to_spec.contains_requirable_file? path
469: end
470:
471: next if trails.empty?
472:
473: return trails.map(&:reverse).sort.first.reverse
474: end
475:
476: []
477: 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 487
487: def self.from_yaml(input)
488: Gem.load_yaml
489:
490: input = normalize_yaml_input input
491: spec = YAML.load input
492:
493: if spec && spec.class == FalseClass then
494: raise Gem::EndOfYAMLException
495: end
496:
497: unless Gem::Specification === spec then
498: raise Gem::Exception, "YAML data doesn't evaluate to gem specification"
499: end
500:
501: unless (spec.instance_variables.include? '@specification_version' or
502: spec.instance_variables.include? :@specification_version) and
503: spec.instance_variable_get :@specification_version
504: spec.instance_variable_set :@specification_version,
505: NONEXISTENT_SPECIFICATION_VERSION
506: end
507:
508: spec
509: end
Return the latest specs, optionally including prerelease specs if prerelease is true.
# File lib/rubygems/specification.rb, line 515
515: def self.latest_specs prerelease = false
516: result = Hash.new { |h,k| h[k] = {} }
517: native = {}
518:
519: Gem::Specification._all.reverse_each do |spec|
520: next if spec.version.prerelease? unless prerelease
521:
522: native[spec.name] = spec.version if spec.platform == Gem::Platform::RUBY
523: result[spec.name][spec.platform] = spec
524: end
525:
526: result.map(&:last).map(&:values).flatten.reject { |spec|
527: minimum = native[spec.name]
528: minimum && spec.version < minimum
529: }
530: end
Loads Ruby format gemspec from file.
# File lib/rubygems/specification.rb, line 535
535: def self.load file
536: return unless file && File.file?(file)
537:
538: file = file.dup.untaint
539:
540: code = if defined? Encoding
541: File.read file, :mode => 'r:UTF-8:-'
542: else
543: File.read file
544: end
545:
546: code.untaint
547:
548: begin
549: spec = eval code, binding, file
550:
551: if Gem::Specification === spec
552: spec.loaded_from = file.to_s
553: return spec
554: end
555:
556: warn "[#{file}] isn't a Gem::Specification (#{spec.class} instead)."
557: rescue SignalException, SystemExit
558: raise
559: rescue SyntaxError, Exception => e
560: warn "Invalid gemspec in [#{file}]: #{e}"
561: end
562:
563: nil
564: 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 1343
1343: def initialize name = nil, version = nil
1344: @loaded = false
1345: @activated = false
1346: @loaded_from = nil
1347: @original_platform = nil
1348:
1349: @@nil_attributes.each do |key|
1350: instance_variable_set "@#{key}", nil
1351: end
1352:
1353: @@non_nil_attributes.each do |key|
1354: default = default_value(key)
1355: value = case default
1356: when Time, Numeric, Symbol, true, false, nil then default
1357: else default.dup
1358: end
1359:
1360: instance_variable_set "@#{key}", value
1361: end
1362:
1363: @new_platform = Gem::Platform::RUBY
1364:
1365: self.name = name if name
1366: self.version = version if version
1367:
1368: yield self if block_given?
1369: end
Specification attributes that must be non-nil
# File lib/rubygems/specification.rb, line 569
569: def self.non_nil_attributes
570: @@non_nil_attributes.dup
571: end
Make sure the YAML specification is properly formatted with dashes
# File lib/rubygems/specification.rb, line 576
576: def self.normalize_yaml_input(input)
577: result = input.respond_to?(:read) ? input.read : input
578: result = "--- " + result unless result =~ /\A--- /
579: result.gsub!(/ !!null \n/, " \n")
580: # date: 2011-04-26 00:00:00.000000000Z
581: # date: 2011-04-26 00:00:00.000000000 Z
582: result.gsub!(/^(date: \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+?)Z/, '\1 Z')
583: result
584: 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 590
590: def self.outdated
591: outdateds = []
592:
593: # TODO: maybe we should switch to rubygems' version service?
594: fetcher = Gem::SpecFetcher.fetcher
595:
596: latest_specs.each do |local|
597: dependency = Gem::Dependency.new local.name, ">= #{local.version}"
598: remotes = fetcher.find_matching dependency
599: remotes = remotes.map { |(_, version, _), _| version }
600: latest = remotes.sort.last
601:
602: outdateds << local.name if latest and local.version < latest
603: end
604:
605: outdateds
606: end
Removes spec from the known specs.
# File lib/rubygems/specification.rb, line 611
611: def self.remove_spec spec
612: # TODO: beat on the tests
613: raise "wtf: #{spec.full_name} not in #{all_names.inspect}" unless
614: _all.include? spec
615: _all.delete spec
616: end
Is name a required attribute?
# File lib/rubygems/specification.rb, line 621
621: def self.required_attribute?(name)
622: @@required_attributes.include? name.to_sym
623: end
Required specification attributes
# File lib/rubygems/specification.rb, line 628
628: def self.required_attributes
629: @@required_attributes.dup
630: end
Reset the list of known specs, running pre and post reset hooks registered in Gem.
# File lib/rubygems/specification.rb, line 636
636: def self.reset
637: @@dirs = nil
638: # from = caller.first(10).reject { |s| s =~ /minitest/ }
639: # warn ""
640: # warn "NOTE: Specification.reset from #{from.inspect}"
641: Gem.pre_reset_hooks.each { |hook| hook.call }
642: @@all = nil
643: Gem.post_reset_hooks.each { |hook| hook.call }
644: end
Dump only crucial instance variables.
# File lib/rubygems/specification.rb, line 716
716: def _dump(limit)
717: Marshal.dump [
718: @rubygems_version,
719: @specification_version,
720: @name,
721: @version,
722: date,
723: @summary,
724: @required_ruby_version,
725: @required_rubygems_version,
726: @original_platform,
727: @dependencies,
728: @rubyforge_project,
729: @email,
730: @authors,
731: @description,
732: @homepage,
733: true, # has_rdoc
734: @new_platform,
735: @licenses
736: ]
737: 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 745
745: def activate
746: raise_if_conflicts
747:
748: return false if Gem.loaded_specs[self.name]
749:
750: activate_dependencies
751: add_self_to_load_path
752:
753: Gem.loaded_specs[self.name] = self
754: @activated = true
755: @loaded = true
756:
757: return true
758: 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 765
765: def activate_dependencies
766: self.runtime_dependencies.each do |spec_dep|
767: if loaded = Gem.loaded_specs[spec_dep.name]
768: next if spec_dep.matches_spec? loaded
769:
770: msg = "can't satisfy '#{spec_dep}', already activated '#{loaded.full_name}'"
771: e = Gem::LoadError.new msg
772: e.name = spec_dep.name
773:
774: raise e
775: end
776:
777: specs = spec_dep.to_specs
778:
779: if specs.size == 1 then
780: specs.first.activate
781: else
782: name = spec_dep.name
783: Gem.unresolved_deps[name] = Gem.unresolved_deps[name].merge spec_dep
784: end
785: end
786:
787: Gem.unresolved_deps.delete self.name
788: end
Returns an array with bindir attached to each executable in the executables list
# File lib/rubygems/specification.rb, line 794
794: def add_bindir(executables)
795: return nil if executables.nil?
796:
797: if @bindir then
798: Array(executables).map { |e| File.join(@bindir, e) }
799: else
800: executables
801: end
802: rescue
803: return nil
804: 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 838
838: def add_development_dependency(gem, *requirements)
839: add_dependency_with_type(gem, :development, *requirements)
840: 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 848
848: def add_runtime_dependency(gem, *requirements)
849: add_dependency_with_type(gem, :runtime, *requirements)
850: end
Adds this spec‘s require paths to LOAD_PATH, in the proper location.
# File lib/rubygems/specification.rb, line 857
857: def add_self_to_load_path
858: paths = require_paths.map do |path|
859: File.join full_gem_path, path
860: end
861:
862: # gem directories must come after -I and ENV['RUBYLIB']
863: insert_index = Gem.load_path_insert_index
864:
865: if insert_index then
866: # gem directories must come after -I and ENV['RUBYLIB']
867: $LOAD_PATH.insert(insert_index, *paths)
868: else
869: # we are probably testing in core, -I and RUBYLIB don't apply
870: $LOAD_PATH.unshift(*paths)
871: end
872: 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 898
898: def authors
899: @authors ||= []
900: end
Returns the full path to the base gem directory.
eg: /usr/local/lib/ruby/gems/1.8
# File lib/rubygems/specification.rb, line 914
914: def base_dir
915: return Gem.dir unless loaded_from
916: @base_dir ||= File.dirname File.dirname loaded_from
917: 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 925
925: def bin_dir
926: @bin_dir ||= File.join gem_dir, bindir # TODO: this is unfortunate
927: end
Returns the full path to an executable named name in this gem.
# File lib/rubygems/specification.rb, line 932
932: def bin_file name
933: File.join bin_dir, name
934: end
Returns the full path to the cache directory containing this spec‘s cached gem.
# File lib/rubygems/specification.rb, line 940
940: def cache_dir
941: @cache_dir ||= File.join base_dir, "cache"
942: end
Returns the full path to the cached gem for this spec.
# File lib/rubygems/specification.rb, line 947
947: def cache_file
948: @cache_file ||= File.join cache_dir, "#{full_name}.gem"
949: end
Return any possible conflicts against the currently loaded specs.
# File lib/rubygems/specification.rb, line 956
956: def conflicts
957: conflicts = {}
958: Gem.loaded_specs.values.each do |spec|
959: bad = self.runtime_dependencies.find_all { |dep|
960: spec.name == dep.name and not spec.satisfies_requirement? dep
961: }
962:
963: conflicts[spec] = bad unless bad.empty?
964: end
965: conflicts
966: end
Return true if this spec can require file.
# File lib/rubygems/specification.rb, line 971
971: def contains_requirable_file? file
972: root = full_gem_path
973:
974: require_paths.each do |lib|
975: base = "#{root}/#{lib}/#{file}"
976: Gem.suffixes.each do |suf|
977: path = "#{base}#{suf}"
978: return true if File.file? path
979: end
980: end
981:
982: return false
983: 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 997
997: def date= date
998: # We want to end up with a Time object with one-day resolution.
999: # This is the cleanest, most-readable, faster-than-using-Date
1000: # way to do it.
1001: @date = case date
1002: when String then
1003: if /\A(\d{4})-(\d{2})-(\d{2})\Z/ =~ date then
1004: Time.utc($1.to_i, $2.to_i, $3.to_i)
1005:
1006: # Workaround for where the date format output from psych isn't
1007: # parsed as a Time object by syck and thus comes through as a
1008: # string.
1009: elsif /\A(\d{4})-(\d{2})-(\d{2}) \d{2}:\d{2}:\d{2}\.\d+?Z\z/ =~ date then
1010: Time.utc($1.to_i, $2.to_i, $3.to_i)
1011: else
1012: raise(Gem::InvalidSpecificationException,
1013: "invalid date format in specification: #{date.inspect}")
1014: end
1015: when Time, Date then
1016: Time.utc(date.year, date.month, date.day)
1017: else
1018: TODAY
1019: end
1020: 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 1028
1028: def default_executable
1029: if defined?(@default_executable) and @default_executable
1030: result = @default_executable
1031: elsif @executables and @executables.size == 1
1032: result = Array(@executables).first
1033: else
1034: result = nil
1035: end
1036: result
1037: end
The default value for specification attribute name
# File lib/rubygems/specification.rb, line 1042
1042: def default_value name
1043: @@default_value[name]
1044: 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 1052
1052: def dependencies
1053: @dependencies ||= []
1054: 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 1062
1062: def dependent_gems
1063: out = []
1064: Gem::Specification.each do |spec|
1065: spec.dependencies.each do |dep|
1066: if self.satisfies_requirement?(dep) then
1067: sats = []
1068: find_all_satisfiers(dep) do |sat|
1069: sats << sat
1070: end
1071: out << [spec, dep, sats]
1072: end
1073: end
1074: end
1075: out
1076: end
Returns all specs that matches this spec‘s runtime dependencies.
# File lib/rubygems/specification.rb, line 1081
1081: def dependent_specs
1082: runtime_dependencies.map { |dep| dep.to_specs }.flatten
1083: end
A long description of this gem
# File lib/rubygems/specification.rb, line 1088
1088: def description= str
1089: @description = str.to_s
1090: end
List of dependencies that are used for development
# File lib/rubygems/specification.rb, line 1095
1095: def development_dependencies
1096: dependencies.select { |d| d.type == :development }
1097: end
Returns the full path to this spec‘s documentation directory.
# File lib/rubygems/specification.rb, line 1102
1102: def doc_dir
1103: @doc_dir ||= File.join base_dir, 'doc', full_name
1104: end
Singular accessor for executables
# File lib/rubygems/specification.rb, line 1134
1134: def executable
1135: val = executables and val.first
1136: end
Singular accessor for executables
# File lib/rubygems/specification.rb, line 1141
1141: def executable=o
1142: self.executables = [o]
1143: end
Executables included in the gem.
# File lib/rubygems/specification.rb, line 1148
1148: def executables
1149: @executables ||= []
1150: 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 1156
1156: def executables= value
1157: # TODO: warn about setting instead of pushing
1158: @executables = Array(value)
1159: end
Extensions to build when installing the gem. See Gem::Installer#build_extensions for valid values.
# File lib/rubygems/specification.rb, line 1165
1165: def extensions
1166: @extensions ||= []
1167: 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 1173
1173: def extensions= extensions
1174: # TODO: warn about setting instead of pushing
1175: @extensions = Array extensions
1176: 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 1189
1189: def extra_rdoc_files= files
1190: # TODO: warn about setting instead of pushing
1191: @extra_rdoc_files = Array files
1192: 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 1212
1212: def files
1213: # DO NOT CHANGE TO ||= ! This is not a normal accessor. (yes, it sucks)
1214: @files = [@files,
1215: @test_files,
1216: add_bindir(@executables),
1217: @extra_rdoc_files,
1218: @extensions,
1219: ].flatten.uniq.compact
1220: end
Creates a duplicate spec without large blobs that aren‘t used at runtime.
# File lib/rubygems/specification.rb, line 1243
1243: def for_cache
1244: spec = dup
1245:
1246: spec.files = nil
1247: spec.test_files = nil
1248:
1249: spec
1250: end
The full path to the gem (install path + full name).
# File lib/rubygems/specification.rb, line 1255
1255: def full_gem_path
1256: # TODO: try to get rid of this... or the awkward
1257: # TODO: also, shouldn't it default to full_name if it hasn't been written?
1258: return @full_gem_path if defined?(@full_gem_path) && @full_gem_path
1259:
1260: @full_gem_path = File.expand_path File.join(gems_dir, full_name)
1261:
1262: return @full_gem_path if File.directory? @full_gem_path
1263:
1264: @full_gem_path = File.expand_path File.join(gems_dir, original_name)
1265: 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 1272
1272: def full_name
1273: if platform == Gem::Platform::RUBY or platform.nil? then
1274: "#{@name}-#{@version}"
1275: else
1276: "#{@name}-#{@version}-#{platform}"
1277: end
1278: 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 1284
1284: def gem_dir
1285: @gem_dir ||= File.expand_path File.join(gems_dir, full_name)
1286: 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 1292
1292: def gems_dir
1293: # TODO: this logic seems terribly broken, but tests fail if just base_dir
1294: @gems_dir ||= File.join(loaded_from && base_dir || Gem.dir, "gems")
1295: end
Deprecated and ignored, defaults to true.
Formerly used to indicate this gem was RDoc-capable.
# File lib/rubygems/specification.rb, line 1302
1302: def has_rdoc
1303: true
1304: end
Deprecated and ignored.
Formerly used to indicate this gem was RDoc-capable.
# File lib/rubygems/specification.rb, line 1311
1311: def has_rdoc= ignored
1312: @has_rdoc = true
1313: end
True if this gem has files in test_files
# File lib/rubygems/specification.rb, line 1320
1320: def has_unit_tests?
1321: not test_files.empty?
1322: end
Duplicates array_attributes from other_spec so state isn‘t shared.
# File lib/rubygems/specification.rb, line 1374
1374: def initialize_copy other_spec
1375: other_ivars = other_spec.instance_variables
1376: other_ivars = other_ivars.map { |ivar| ivar.intern } if # for 1.9
1377: String === other_ivars.first
1378:
1379: self.class.array_attributes.each do |name|
1380: name = "@#{name}""@#{name}"
1381: next unless other_ivars.include? name
1382:
1383: begin
1384: val = other_spec.instance_variable_get(name)
1385: if val then
1386: instance_variable_set name, val.dup
1387: elsif Gem.configuration.really_verbose
1388: warn "WARNING: #{full_name} has an invalid nil value for #{name}"
1389: end
1390: rescue TypeError
1391: e = Gem::FormatException.new \
1392: "#{full_name} has an invalid value for #{name}"
1393:
1394: e.file_path = loaded_from
1395: raise e
1396: end
1397: end
1398: end
Returns a string usable in Dir.glob to match all requirable paths for this spec.
# File lib/rubygems/specification.rb, line 1412
1412: def lib_dirs_glob
1413: dirs = if self.require_paths.size > 1 then
1414: "{#{self.require_paths.join(',')}}"
1415: else
1416: self.require_paths.first
1417: end
1418:
1419: "#{self.full_gem_path}/#{dirs}"
1420: end
Set the location a Specification was loaded from. obj is converted to a String.
# File lib/rubygems/specification.rb, line 1466
1466: def loaded_from= path
1467: @loaded_from = path.to_s
1468: end
Sets the rubygems_version to the current RubyGems version.
# File lib/rubygems/specification.rb, line 1473
1473: def mark_version
1474: @rubygems_version = Gem::VERSION
1475: end
Return all files in this gem that match for glob.
# File lib/rubygems/specification.rb, line 1480
1480: def matches_for_glob glob # TODO: rename?
1481: # TODO: do we need these?? Kill it
1482: glob = File.join(self.lib_dirs_glob, glob)
1483:
1484: Dir[glob].map { |f| f.untaint } # FIX our tests are broken, run w/ SAFE=1
1485: end
Normalize the list of files so that:
# File lib/rubygems/specification.rb, line 1505
1505: def normalize
1506: if defined?(@extra_rdoc_files) and @extra_rdoc_files then
1507: @extra_rdoc_files.uniq!
1508: @files ||= []
1509: @files.concat(@extra_rdoc_files)
1510: end
1511:
1512: @files = @files.uniq if @files
1513: @extensions = @extensions.uniq if @extensions
1514: @test_files = @test_files.uniq if @test_files
1515: @executables = @executables.uniq if @executables
1516: @extra_rdoc_files = @extra_rdoc_files.uniq if @extra_rdoc_files
1517: end
The platform this gem runs on. See Gem::Platform for details.
# File lib/rubygems/specification.rb, line 1541
1541: def platform
1542: @new_platform ||= Gem::Platform::RUBY
1543: 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 1551
1551: def platform= platform
1552: if @original_platform.nil? or
1553: @original_platform == Gem::Platform::RUBY then
1554: @original_platform = platform
1555: end
1556:
1557: case platform
1558: when Gem::Platform::CURRENT then
1559: @new_platform = Gem::Platform.local
1560: @original_platform = @new_platform.to_s
1561:
1562: when Gem::Platform then
1563: @new_platform = platform
1564:
1565: # legacy constants
1566: when nil, Gem::Platform::RUBY then
1567: @new_platform = Gem::Platform::RUBY
1568: when 'mswin32' then # was Gem::Platform::WIN32
1569: @new_platform = Gem::Platform.new 'x86-mswin32'
1570: when 'i586-linux' then # was Gem::Platform::LINUX_586
1571: @new_platform = Gem::Platform.new 'x86-linux'
1572: when 'powerpc-darwin' then # was Gem::Platform::DARWIN
1573: @new_platform = Gem::Platform.new 'ppc-darwin'
1574: else
1575: @new_platform = Gem::Platform.new platform
1576: end
1577:
1578: @platform = @new_platform.to_s
1579:
1580: @new_platform
1581: end
Check the spec for possible conflicts and freak out if there are any.
# File lib/rubygems/specification.rb, line 1612
1612: def raise_if_conflicts
1613: other = Gem.loaded_specs[self.name]
1614:
1615: if other and self.version != other.version then
1616: # This gem is already loaded. If the currently loaded gem is not in the
1617: # list of candidate gems, then we have a version conflict.
1618:
1619: msg = "can't activate #{full_name}, already activated #{other.full_name}"
1620:
1621: e = Gem::LoadError.new msg
1622: e.name = self.name
1623: # TODO: e.requirement = dep.requirement
1624:
1625: raise e
1626: end
1627:
1628: conf = self.conflicts
1629:
1630: unless conf.empty? then
1631: y = conf.map { |act,con|
1632: "#{act.full_name} conflicts with #{con.join(", ")}"
1633: }.join ", "
1634:
1635: # TODO: improve message by saying who activated `con`
1636:
1637: raise Gem::LoadError, "Unable to activate #{self.full_name}, because #{y}"
1638: end
1639: end
An ARGV style array of options to RDoc
# File lib/rubygems/specification.rb, line 1644
1644: def rdoc_options
1645: @rdoc_options ||= []
1646: 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 1652
1652: def rdoc_options= options
1653: # TODO: warn about setting instead of pushing
1654: @rdoc_options = Array options
1655: end
Singular accessor for require_paths
# File lib/rubygems/specification.rb, line 1660
1660: def require_path
1661: val = require_paths and val.first
1662: end
Singular accessor for require_paths
# File lib/rubygems/specification.rb, line 1667
1667: def require_path= path
1668: self.require_paths = [path]
1669: end
The version of ruby required by this gem
# File lib/rubygems/specification.rb, line 1674
1674: def required_ruby_version= req
1675: @required_ruby_version = Gem::Requirement.create req
1676: end
The RubyGems version required by this gem
# File lib/rubygems/specification.rb, line 1681
1681: def required_rubygems_version= req
1682: @required_rubygems_version = Gem::Requirement.create req
1683: end
An array or things required by this gem. Not used by anything presently.
# File lib/rubygems/specification.rb, line 1689
1689: def requirements
1690: @requirements ||= []
1691: 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 1697
1697: def requirements= req
1698: # TODO: warn about setting instead of pushing
1699: @requirements = Array req
1700: end
Returns the full path to this spec‘s ri directory.
# File lib/rubygems/specification.rb, line 1705
1705: def ri_dir
1706: @ri_dir ||= File.join base_dir, 'ri', full_name
1707: end
List of dependencies that will automatically be activated at runtime.
# File lib/rubygems/specification.rb, line 1733
1733: def runtime_dependencies
1734: dependencies.select { |d| d.type == :runtime }
1735: end
Checks if this specification meets the requirement of dependency.
# File lib/rubygems/specification.rb, line 1749
1749: def satisfies_requirement? dependency
1750: return @name == dependency.name &&
1751: dependency.requirement.satisfied_by?(@version)
1752: end
Returns an object you can use to sort specifications in sort_by.
# File lib/rubygems/specification.rb, line 1757
1757: def sort_obj
1758: # TODO: this is horrible. Deprecate it.
1759: [@name, @version, @new_platform == Gem::Platform::RUBY ? -1 : 1]
1760: 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 1766
1766: def spec_dir
1767: @spec_dir ||= File.join base_dir, "specifications"
1768: 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 1774
1774: def spec_file
1775: @spec_file ||= File.join spec_dir, "#{full_name}.gemspec"
1776: end
A short summary of this gem‘s description.
# File lib/rubygems/specification.rb, line 1790
1790: def summary= str
1791: @summary = str.to_s.strip.
1792: gsub(/(\w-)\n[ \t]*(\w)/, '\1\2').gsub(/\n[ \t]*/, " ") # so. weird.
1793: end
Singular accessor for test_files
# File lib/rubygems/specification.rb, line 1798
1798: def test_file
1799: val = test_files and val.first
1800: end
Singular accessor for test_files
# File lib/rubygems/specification.rb, line 1805
1805: def test_file= file
1806: self.test_files = [file]
1807: end
Test files included in this gem. You cannot append to this accessor, you must assign to it.
# File lib/rubygems/specification.rb, line 1813
1813: def test_files
1814: # Handle the possibility that we have @test_suite_file but not
1815: # @test_files. This will happen when an old gem is loaded via
1816: # YAML.
1817: if defined? @test_suite_file then
1818: @test_files = [@test_suite_file].flatten
1819: @test_suite_file = nil
1820: end
1821: if defined?(@test_files) and @test_files then
1822: @test_files
1823: else
1824: @test_files = []
1825: end
1826: end
Set test_files to files, ensuring it is an array.
# File lib/rubygems/specification.rb, line 1831
1831: def test_files= files
1832: @test_files = Array files
1833: 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 1851
1851: def to_ruby
1852: mark_version
1853: result = []
1854: result << "# -*- encoding: utf-8 -*-"
1855: result << nil
1856: result << "Gem::Specification.new do |s|"
1857:
1858: result << " s.name = #{ruby_code name}"
1859: result << " s.version = #{ruby_code version}"
1860: unless platform.nil? or platform == Gem::Platform::RUBY then
1861: result << " s.platform = #{ruby_code original_platform}"
1862: end
1863: result << ""
1864: result << " s.required_rubygems_version = #{ruby_code required_rubygems_version} if s.respond_to? :required_rubygems_version="
1865:
1866: handled = [
1867: :dependencies,
1868: :name,
1869: :platform,
1870: :required_rubygems_version,
1871: :specification_version,
1872: :version,
1873: :has_rdoc,
1874: :default_executable,
1875: ]
1876:
1877: @@attributes.each do |attr_name|
1878: next if handled.include? attr_name
1879: current_value = self.send(attr_name)
1880: if current_value != default_value(attr_name) or
1881: self.class.required_attribute? attr_name then
1882: result << " s.#{attr_name} = #{ruby_code current_value}"
1883: end
1884: end
1885:
1886: result << nil
1887: result << " if s.respond_to? :specification_version then"
1888: result << " s.specification_version = #{specification_version}"
1889: result << nil
1890:
1891: result << " if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then"
1892:
1893: dependencies.each do |dep|
1894: req = dep.requirements_list.inspect
1895: dep.instance_variable_set :@type, :runtime if dep.type.nil? # HACK
1896: result << " s.add_#{dep.type}_dependency(%q<#{dep.name}>, #{req})"
1897: end
1898:
1899: result << " else"
1900:
1901: dependencies.each do |dep|
1902: version_reqs_param = dep.requirements_list.inspect
1903: result << " s.add_dependency(%q<#{dep.name}>, #{version_reqs_param})"
1904: end
1905:
1906: result << ' end'
1907:
1908: result << " else"
1909: dependencies.each do |dep|
1910: version_reqs_param = dep.requirements_list.inspect
1911: result << " s.add_dependency(%q<#{dep.name}>, #{version_reqs_param})"
1912: end
1913: result << " end"
1914:
1915: result << "end"
1916: result << nil
1917:
1918: result.join "\n"
1919: end
Recursively walk dependencies of this spec, executing the block for each hop.
# File lib/rubygems/specification.rb, line 1966
1966: def traverse trail = [], &block
1967: trail = trail + [self]
1968: runtime_dependencies.each do |dep|
1969: dep.to_specs.each do |dep_spec|
1970: block[self, dep, dep_spec, trail + [dep_spec]]
1971: dep_spec.traverse(trail, &block) unless
1972: trail.map(&:name).include? dep_spec.name
1973: end
1974: end
1975: 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 1984
1984: def validate packaging = true
1985: require 'rubygems/user_interaction'
1986: extend Gem::UserInteraction
1987: normalize
1988:
1989: nil_attributes = self.class.non_nil_attributes.find_all do |name|
1990: instance_variable_get("@#{name}").nil?
1991: end
1992:
1993: unless nil_attributes.empty? then
1994: raise Gem::InvalidSpecificationException,
1995: "#{nil_attributes.join ', '} must not be nil"
1996: end
1997:
1998: if packaging and rubygems_version != Gem::VERSION then
1999: raise Gem::InvalidSpecificationException,
2000: "expected RubyGems version #{Gem::VERSION}, was #{rubygems_version}"
2001: end
2002:
2003: @@required_attributes.each do |symbol|
2004: unless self.send symbol then
2005: raise Gem::InvalidSpecificationException,
2006: "missing value for attribute #{symbol}"
2007: end
2008: end
2009:
2010: unless String === name then
2011: raise Gem::InvalidSpecificationException,
2012: "invalid value for attribute name: \"#{name.inspect}\""
2013: end
2014:
2015: if require_paths.empty? then
2016: raise Gem::InvalidSpecificationException,
2017: 'specification must have at least one require_path'
2018: end
2019:
2020: @files.delete_if { |x| File.directory?(x) }
2021: @test_files.delete_if { |x| File.directory?(x) }
2022: @executables.delete_if { |x| File.directory?(File.join(@bindir, x)) }
2023: @extra_rdoc_files.delete_if { |x| File.directory?(x) }
2024: @extensions.delete_if { |x| File.directory?(x) }
2025:
2026: non_files = files.reject { |x| File.file?(x) }
2027:
2028: unless not packaging or non_files.empty? then
2029: raise Gem::InvalidSpecificationException,
2030: "[\"#{non_files.join "\", \""}\"] are not files"
2031: end
2032:
2033: unless specification_version.is_a?(Fixnum)
2034: raise Gem::InvalidSpecificationException,
2035: 'specification_version must be a Fixnum (did you mean version?)'
2036: end
2037:
2038: case platform
2039: when Gem::Platform, Gem::Platform::RUBY then # ok
2040: else
2041: raise Gem::InvalidSpecificationException,
2042: "invalid platform #{platform.inspect}, see Gem::Platform"
2043: end
2044:
2045: self.class.array_attributes.each do |field|
2046: val = self.send field
2047: klass = case field
2048: when :dependencies
2049: Gem::Dependency
2050: else
2051: String
2052: end
2053:
2054: unless Array === val and val.all? { |x| x.kind_of?(klass) } then
2055: raise(Gem::InvalidSpecificationException,
2056: "#{field} must be an Array of #{klass}")
2057: end
2058: end
2059:
2060: [:authors].each do |field|
2061: val = self.send field
2062: raise Gem::InvalidSpecificationException, "#{field} may not be empty" if
2063: val.empty?
2064: end
2065:
2066: licenses.each { |license|
2067: if license.length > 64
2068: raise Gem::InvalidSpecificationException,
2069: "each license must be 64 characters or less"
2070: end
2071: }
2072:
2073: # reject lazy developers:
2074:
2075: lazy = '"FIxxxXME" or "TOxxxDO"'.gsub(/xxx/, '')
2076:
2077: unless authors.grep(/FI XME|TO DO/x).empty? then
2078: raise Gem::InvalidSpecificationException, "#{lazy} is not an author"
2079: end
2080:
2081: unless Array(email).grep(/FI XME|TO DO/x).empty? then
2082: raise Gem::InvalidSpecificationException, "#{lazy} is not an email"
2083: end
2084:
2085: if description =~ /FI XME|TO DO/x then
2086: raise Gem::InvalidSpecificationException, "#{lazy} is not a description"
2087: end
2088:
2089: if summary =~ /FI XME|TO DO/x then
2090: raise Gem::InvalidSpecificationException, "#{lazy} is not a summary"
2091: end
2092:
2093: if homepage and not homepage.empty? and
2094: homepage !~ /\A[a-z][a-z\d+.-]*:/i then
2095: raise Gem::InvalidSpecificationException,
2096: "\"#{homepage}\" is not a URI"
2097: end
2098:
2099: # Warnings
2100:
2101: %w[author description email homepage summary].each do |attribute|
2102: value = self.send attribute
2103: alert_warning "no #{attribute} specified" if value.nil? or value.empty?
2104: end
2105:
2106: if description == summary then
2107: alert_warning 'description and summary are identical'
2108: end
2109:
2110: # TODO: raise at some given date
2111: alert_warning "deprecated autorequire specified" if autorequire
2112:
2113: executables.each do |executable|
2114: executable_path = File.join(bindir, executable)
2115: shebang = File.read(executable_path, 2) == '#!'
2116:
2117: alert_warning "#{executable_path} is missing #! line" unless shebang
2118: end
2119:
2120: true
2121: 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 2128
2128: def version= version
2129: @version = Gem::Version.create(version)
2130: self.required_rubygems_version = '> 1.3.1' if @version.prerelease?
2131: return @version
2132: end