/tools/Ruby/lib/ruby/site_ruby/1.8/rubygems/specification.rb

http://github.com/agross/netopenspace · Ruby · 1543 lines · 871 code · 320 blank · 352 comment · 70 complexity · fc0af9b8a1904db3f1415f3b7853b7c1 MD5 · raw file

  1. #--
  2. # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
  3. # All rights reserved.
  4. # See LICENSE.txt for permissions.
  5. #++
  6. require 'rubygems/version'
  7. require 'rubygems/requirement'
  8. require 'rubygems/platform'
  9. require "rubygems/deprecate"
  10. # :stopdoc:
  11. class Date; end # for ruby_code if date.rb wasn't required
  12. # :startdoc:
  13. ##
  14. # The Specification class contains the metadata for a Gem. Typically
  15. # defined in a .gemspec file or a Rakefile, and looks like this:
  16. #
  17. # spec = Gem::Specification.new do |s|
  18. # s.name = 'example'
  19. # s.version = '1.0'
  20. # s.summary = 'Example gem specification'
  21. # ...
  22. # end
  23. #
  24. # For a great way to package gems, use Hoe.
  25. class Gem::Specification
  26. ##
  27. # Allows deinstallation of gems with legacy platforms.
  28. attr_accessor :original_platform # :nodoc:
  29. ##
  30. # The the version number of a specification that does not specify one
  31. # (i.e. RubyGems 0.7 or earlier).
  32. NONEXISTENT_SPECIFICATION_VERSION = -1
  33. ##
  34. # The specification version applied to any new Specification instances
  35. # created. This should be bumped whenever something in the spec format
  36. # changes.
  37. #
  38. # Specification Version History:
  39. #
  40. # spec ruby
  41. # ver ver yyyy-mm-dd description
  42. # -1 <0.8.0 pre-spec-version-history
  43. # 1 0.8.0 2004-08-01 Deprecated "test_suite_file" for "test_files"
  44. # "test_file=x" is a shortcut for "test_files=[x]"
  45. # 2 0.9.5 2007-10-01 Added "required_rubygems_version"
  46. # Now forward-compatible with future versions
  47. # 3 1.3.2 2009-01-03 Added Fixnum validation to specification_version
  48. #--
  49. # When updating this number, be sure to also update #to_ruby.
  50. #
  51. # NOTE RubyGems < 1.2 cannot load specification versions > 2.
  52. CURRENT_SPECIFICATION_VERSION = 3
  53. # :stopdoc:
  54. # version => # of fields
  55. MARSHAL_FIELDS = { -1 => 16, 1 => 16, 2 => 16, 3 => 17 }
  56. today = Time.now.utc
  57. TODAY = Time.utc(today.year, today.month, today.day)
  58. # :startdoc:
  59. ##
  60. # List of attribute names: [:name, :version, ...]
  61. @@required_attributes = [:rubygems_version,
  62. :specification_version,
  63. :name,
  64. :version,
  65. :date,
  66. :summary,
  67. :require_paths]
  68. ##
  69. # Map of attribute names to default values.
  70. @@default_value = {
  71. :authors => [],
  72. :autorequire => nil,
  73. :bindir => "bin",
  74. :cert_chain => [],
  75. :date => TODAY,
  76. :dependencies => [],
  77. :description => nil,
  78. :email => nil,
  79. :executables => [],
  80. :extensions => [],
  81. :extra_rdoc_files => [],
  82. :files => [],
  83. :homepage => nil,
  84. :licenses => [],
  85. :name => nil,
  86. :platform => Gem::Platform::RUBY,
  87. :post_install_message => nil,
  88. :rdoc_options => [],
  89. :require_paths => ["lib"],
  90. :required_ruby_version => Gem::Requirement.default,
  91. :required_rubygems_version => Gem::Requirement.default,
  92. :requirements => [],
  93. :rubyforge_project => nil,
  94. :rubygems_version => Gem::VERSION,
  95. :signing_key => nil,
  96. :specification_version => CURRENT_SPECIFICATION_VERSION,
  97. :summary => nil,
  98. :test_files => [],
  99. :version => nil,
  100. }
  101. @@attributes = @@default_value.keys.sort_by { |s| s.to_s }
  102. @@array_attributes = @@default_value.reject { |k,v| v != [] }.keys
  103. @@nil_attributes, @@non_nil_attributes = @@default_value.keys.partition { |k|
  104. @@default_value[k].nil?
  105. }
  106. def self.attribute_names
  107. @@attributes.dup
  108. end
  109. ##
  110. # The default value for specification attribute +name+
  111. def default_value(name)
  112. @@default_value[name]
  113. end
  114. ##
  115. # Required specification attributes
  116. def self.required_attributes
  117. @@required_attributes.dup
  118. end
  119. ##
  120. # Is +name+ a required attribute?
  121. def self.required_attribute?(name)
  122. @@required_attributes.include? name.to_sym
  123. end
  124. ##
  125. # Specification attributes that are arrays (appendable and so-forth)
  126. def self.array_attributes
  127. @@array_attributes.dup
  128. end
  129. ##
  130. # Specification attributes that must be non-nil
  131. def self.non_nil_attributes
  132. @@non_nil_attributes.dup
  133. end
  134. ##
  135. # Dump only crucial instance variables.
  136. #--
  137. # MAINTAIN ORDER!
  138. # (down with the man)
  139. def _dump(limit)
  140. Marshal.dump [
  141. @rubygems_version,
  142. @specification_version,
  143. @name,
  144. @version,
  145. date,
  146. @summary,
  147. @required_ruby_version,
  148. @required_rubygems_version,
  149. @original_platform,
  150. @dependencies,
  151. @rubyforge_project,
  152. @email,
  153. @authors,
  154. @description,
  155. @homepage,
  156. true, # has_rdoc
  157. @new_platform,
  158. @licenses
  159. ]
  160. end
  161. ##
  162. # Load custom marshal format, re-initializing defaults as needed
  163. def self._load(str)
  164. array = Marshal.load str
  165. spec = Gem::Specification.new
  166. spec.instance_variable_set :@specification_version, array[1]
  167. current_version = CURRENT_SPECIFICATION_VERSION
  168. field_count = if spec.specification_version > current_version then
  169. spec.instance_variable_set :@specification_version,
  170. current_version
  171. MARSHAL_FIELDS[current_version]
  172. else
  173. MARSHAL_FIELDS[spec.specification_version]
  174. end
  175. if array.size < field_count then
  176. raise TypeError, "invalid Gem::Specification format #{array.inspect}"
  177. end
  178. spec.instance_variable_set :@rubygems_version, array[0]
  179. # spec version
  180. spec.instance_variable_set :@name, array[2]
  181. spec.instance_variable_set :@version, array[3]
  182. spec.instance_variable_set :@date, array[4]
  183. spec.instance_variable_set :@summary, array[5]
  184. spec.instance_variable_set :@required_ruby_version, array[6]
  185. spec.instance_variable_set :@required_rubygems_version, array[7]
  186. spec.instance_variable_set :@original_platform, array[8]
  187. spec.instance_variable_set :@dependencies, array[9]
  188. spec.instance_variable_set :@rubyforge_project, array[10]
  189. spec.instance_variable_set :@email, array[11]
  190. spec.instance_variable_set :@authors, array[12]
  191. spec.instance_variable_set :@description, array[13]
  192. spec.instance_variable_set :@homepage, array[14]
  193. spec.instance_variable_set :@has_rdoc, array[15]
  194. spec.instance_variable_set :@new_platform, array[16]
  195. spec.instance_variable_set :@platform, array[16].to_s
  196. spec.instance_variable_set :@license, array[17]
  197. spec.instance_variable_set :@loaded, false
  198. spec
  199. end
  200. ##
  201. # List of dependencies that will automatically be activated at runtime.
  202. def runtime_dependencies
  203. dependencies.select { |d| d.type == :runtime }
  204. end
  205. ##
  206. # List of dependencies that are used for development
  207. def development_dependencies
  208. dependencies.select { |d| d.type == :development }
  209. end
  210. def test_suite_file # :nodoc:
  211. test_files.first
  212. end
  213. def test_suite_file=(val) # :nodoc:
  214. @test_files = [] unless defined? @test_files
  215. @test_files << val
  216. end
  217. ##
  218. # true when this gemspec has been loaded from a specifications directory.
  219. # This attribute is not persisted.
  220. attr_accessor :loaded
  221. ##
  222. # Path this gemspec was loaded from. This attribute is not persisted.
  223. attr_accessor :loaded_from
  224. ##
  225. # Returns an array with bindir attached to each executable in the
  226. # executables list
  227. def add_bindir(executables)
  228. return nil if executables.nil?
  229. if @bindir then
  230. Array(executables).map { |e| File.join(@bindir, e) }
  231. else
  232. executables
  233. end
  234. rescue
  235. return nil
  236. end
  237. ##
  238. # Files in the Gem under one of the require_paths
  239. def lib_files
  240. @files.select do |file|
  241. require_paths.any? do |path|
  242. file.index(path) == 0
  243. end
  244. end
  245. end
  246. ##
  247. # True if this gem was loaded from disk
  248. alias :loaded? :loaded
  249. ##
  250. # True if this gem has files in test_files
  251. def has_unit_tests?
  252. not test_files.empty?
  253. end
  254. # :stopdoc:
  255. alias has_test_suite? has_unit_tests?
  256. # :startdoc:
  257. ##
  258. # Specification constructor. Assigns the default values to the
  259. # attributes and yields itself for further
  260. # initialization. Optionally takes +name+ and +version+.
  261. def initialize name = nil, version = nil
  262. @new_platform = nil
  263. @loaded = false
  264. @loaded_from = nil
  265. @original_platform = nil
  266. @@nil_attributes.each do |key|
  267. instance_variable_set "@#{key}", nil
  268. end
  269. @@non_nil_attributes.each do |key|
  270. default = default_value(key)
  271. value = case default
  272. when Time, Numeric, Symbol, true, false, nil then default
  273. else default.dup
  274. end
  275. instance_variable_set "@#{key}", value
  276. end
  277. # HACK
  278. instance_variable_set :@new_platform, Gem::Platform::RUBY
  279. self.name = name if name
  280. self.version = version if version
  281. yield self if block_given?
  282. end
  283. ##
  284. # Duplicates array_attributes from +other_spec+ so state isn't shared.
  285. def initialize_copy(other_spec)
  286. other_ivars = other_spec.instance_variables
  287. other_ivars = other_ivars.map { |ivar| ivar.intern } if # for 1.9
  288. String === other_ivars.first
  289. self.class.array_attributes.each do |name|
  290. name = :"@#{name}"
  291. next unless other_ivars.include? name
  292. begin
  293. val = other_spec.instance_variable_get(name)
  294. if val then
  295. instance_variable_set name, val.dup
  296. else
  297. warn "WARNING: #{full_name} has an invalid nil value for #{name}"
  298. end
  299. rescue TypeError
  300. e = Gem::FormatException.new \
  301. "#{full_name} has an invalid value for #{name}"
  302. e.file_path = loaded_from
  303. raise e
  304. end
  305. end
  306. end
  307. ##
  308. # Special loader for YAML files. When a Specification object is loaded
  309. # from a YAML file, it bypasses the normal Ruby object initialization
  310. # routine (#initialize). This method makes up for that and deals with
  311. # gems of different ages.
  312. #
  313. # 'input' can be anything that YAML.load() accepts: String or IO.
  314. def self.from_yaml(input)
  315. input = normalize_yaml_input input
  316. spec = YAML.load input
  317. if spec && spec.class == FalseClass then
  318. raise Gem::EndOfYAMLException
  319. end
  320. unless Gem::Specification === spec then
  321. raise Gem::Exception, "YAML data doesn't evaluate to gem specification"
  322. end
  323. unless (spec.instance_variables.include? '@specification_version' or
  324. spec.instance_variables.include? :@specification_version) and
  325. spec.instance_variable_get :@specification_version
  326. spec.instance_variable_set :@specification_version,
  327. NONEXISTENT_SPECIFICATION_VERSION
  328. end
  329. spec
  330. end
  331. ##
  332. # Loads Ruby format gemspec from +file+.
  333. def self.load file
  334. return unless file && File.file?(file)
  335. file = file.dup.untaint
  336. code = if defined? Encoding
  337. File.read file, :encoding => "UTF-8"
  338. else
  339. File.read file
  340. end
  341. code.untaint
  342. begin
  343. spec = eval code, binding, file
  344. if Gem::Specification === spec
  345. spec.loaded_from = file
  346. return spec
  347. end
  348. warn "[#{file}] isn't a Gem::Specification (#{spec.class} instead)."
  349. rescue SignalException, SystemExit
  350. raise
  351. rescue SyntaxError, Exception => e
  352. warn "Invalid gemspec in [#{file}]: #{e}"
  353. end
  354. nil
  355. end
  356. ##
  357. # Make sure the YAML specification is properly formatted with dashes
  358. def self.normalize_yaml_input(input)
  359. result = input.respond_to?(:read) ? input.read : input
  360. result = "--- " + result unless result =~ /\A--- /
  361. result.gsub(/ !!null \n/, " \n")
  362. end
  363. ##
  364. # Sets the rubygems_version to the current RubyGems version
  365. def mark_version
  366. @rubygems_version = Gem::VERSION
  367. end
  368. ##
  369. # Ignore unknown attributes while loading
  370. def method_missing(sym, *a, &b) # :nodoc:
  371. if @specification_version > CURRENT_SPECIFICATION_VERSION and
  372. sym.to_s =~ /=$/ then
  373. warn "ignoring #{sym} loading #{full_name}" if $DEBUG
  374. else
  375. super
  376. end
  377. end
  378. ##
  379. # Adds a development dependency named +gem+ with +requirements+ to this
  380. # Gem. For example:
  381. #
  382. # spec.add_development_dependency 'jabber4r', '> 0.1', '<= 0.5'
  383. #
  384. # Development dependencies aren't installed by default and aren't
  385. # activated when a gem is required.
  386. def add_development_dependency(gem, *requirements)
  387. add_dependency_with_type(gem, :development, *requirements)
  388. end
  389. ##
  390. # Adds a runtime dependency named +gem+ with +requirements+ to this Gem.
  391. # For example:
  392. #
  393. # spec.add_runtime_dependency 'jabber4r', '> 0.1', '<= 0.5'
  394. def add_runtime_dependency(gem, *requirements)
  395. add_dependency_with_type(gem, :runtime, *requirements)
  396. end
  397. ##
  398. # Adds a runtime dependency
  399. alias add_dependency add_runtime_dependency
  400. ##
  401. # Returns the full name (name-version) of this Gem. Platform information
  402. # is included (name-version-platform) if it is specified and not the
  403. # default Ruby platform.
  404. def full_name
  405. if platform == Gem::Platform::RUBY or platform.nil? then
  406. "#{@name}-#{@version}"
  407. else
  408. "#{@name}-#{@version}-#{platform}"
  409. end
  410. end
  411. ##
  412. # Returns the full name (name-version) of this gemspec using the original
  413. # platform. For use with legacy gems.
  414. def original_name # :nodoc:
  415. if platform == Gem::Platform::RUBY or platform.nil? then
  416. "#{@name}-#{@version}"
  417. else
  418. "#{@name}-#{@version}-#{@original_platform}"
  419. end
  420. end
  421. ##
  422. # The full path to the gem (install path + full name).
  423. def full_gem_path
  424. path = File.join installation_path, 'gems', full_name
  425. return path if File.directory? path
  426. File.join installation_path, 'gems', original_name
  427. end
  428. ##
  429. # The default (generated) file name of the gem. See also #spec_name.
  430. #
  431. # spec.file_name # => "example-1.0.gem"
  432. def file_name
  433. "#{full_name}.gem"
  434. end
  435. ##
  436. # The directory that this gem was installed into.
  437. def installation_path
  438. unless @loaded_from then
  439. raise Gem::Exception, "spec #{full_name} is not from an installed gem"
  440. end
  441. File.expand_path File.dirname(File.dirname(@loaded_from))
  442. end
  443. ##
  444. # Checks if this specification meets the requirement of +dependency+.
  445. def satisfies_requirement?(dependency)
  446. return @name == dependency.name &&
  447. dependency.requirement.satisfied_by?(@version)
  448. end
  449. ##
  450. # Returns an object you can use to sort specifications in #sort_by.
  451. def sort_obj
  452. [@name, @version, @new_platform == Gem::Platform::RUBY ? -1 : 1]
  453. end
  454. ##
  455. # The default name of the gemspec. See also #file_name
  456. #
  457. # spec.spec_name # => "example-1.0.gemspec"
  458. def spec_name
  459. "#{full_name}.gemspec"
  460. end
  461. def <=>(other) # :nodoc:
  462. sort_obj <=> other.sort_obj
  463. end
  464. ##
  465. # Tests specs for equality (across all attributes).
  466. def ==(other) # :nodoc:
  467. self.class === other && same_attributes?(other)
  468. end
  469. alias eql? == # :nodoc:
  470. ##
  471. # A macro to yield cached gem path
  472. #
  473. def cache_gem
  474. cache_name = File.join(Gem.dir, 'cache', file_name)
  475. return File.exist?(cache_name) ? cache_name : nil
  476. end
  477. ##
  478. # True if this gem has the same attributes as +other+.
  479. def same_attributes?(other)
  480. @@attributes.each do |name, default|
  481. return false unless self.send(name) == other.send(name)
  482. end
  483. true
  484. end
  485. private :same_attributes?
  486. def hash # :nodoc:
  487. @@attributes.inject(0) { |hash_code, (name, _)|
  488. hash_code ^ self.send(name).hash
  489. }
  490. end
  491. def encode_with coder # :nodoc:
  492. mark_version
  493. coder.add 'name', @name
  494. coder.add 'version', @version
  495. platform = case @original_platform
  496. when nil, '' then
  497. 'ruby'
  498. when String then
  499. @original_platform
  500. else
  501. @original_platform.to_s
  502. end
  503. coder.add 'platform', platform
  504. attributes = @@attributes.map(&:to_s) - %w[name version platform]
  505. attributes.each do |name|
  506. coder.add name, instance_variable_get("@#{name}")
  507. end
  508. end
  509. ##
  510. # Creates a duplicate spec without large blobs that aren't used at runtime.
  511. def for_cache
  512. spec = dup
  513. spec.files = nil
  514. spec.test_files = nil
  515. spec
  516. end
  517. def to_yaml(opts = {}) # :nodoc:
  518. if YAML.const_defined?(:ENGINE) && !YAML::ENGINE.syck? then
  519. super.gsub(/ !!null \n/, " \n")
  520. else
  521. YAML.quick_emit object_id, opts do |out|
  522. out.map taguri, to_yaml_style do |map|
  523. encode_with map
  524. end
  525. end
  526. end
  527. end
  528. def init_with coder # :nodoc:
  529. yaml_initialize coder.tag, coder.map
  530. end
  531. def yaml_initialize(tag, vals) # :nodoc:
  532. vals.each do |ivar, val|
  533. instance_variable_set "@#{ivar}", val
  534. end
  535. @original_platform = @platform # for backwards compatibility
  536. self.platform = Gem::Platform.new @platform
  537. end
  538. ##
  539. # Returns a Ruby code representation of this specification, such that it
  540. # can be eval'ed and reconstruct the same specification later. Attributes
  541. # that still have their default values are omitted.
  542. def to_ruby
  543. mark_version
  544. result = []
  545. result << "# -*- encoding: utf-8 -*-"
  546. result << nil
  547. result << "Gem::Specification.new do |s|"
  548. result << " s.name = #{ruby_code name}"
  549. result << " s.version = #{ruby_code version}"
  550. unless platform.nil? or platform == Gem::Platform::RUBY then
  551. result << " s.platform = #{ruby_code original_platform}"
  552. end
  553. result << ""
  554. result << " s.required_rubygems_version = #{ruby_code required_rubygems_version} if s.respond_to? :required_rubygems_version="
  555. handled = [
  556. :dependencies,
  557. :name,
  558. :platform,
  559. :required_rubygems_version,
  560. :specification_version,
  561. :version,
  562. :has_rdoc,
  563. ]
  564. @@attributes.each do |attr_name|
  565. next if handled.include? attr_name
  566. current_value = self.send(attr_name)
  567. if current_value != default_value(attr_name) or
  568. self.class.required_attribute? attr_name then
  569. result << " s.#{attr_name} = #{ruby_code current_value}"
  570. end
  571. end
  572. result << nil
  573. result << " if s.respond_to? :specification_version then"
  574. result << " s.specification_version = #{specification_version}"
  575. result << nil
  576. result << " if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then"
  577. dependencies.each do |dep|
  578. req = dep.requirements_list.inspect
  579. dep.instance_variable_set :@type, :runtime if dep.type.nil? # HACK
  580. result << " s.add_#{dep.type}_dependency(%q<#{dep.name}>, #{req})"
  581. end
  582. result << " else"
  583. dependencies.each do |dep|
  584. version_reqs_param = dep.requirements_list.inspect
  585. result << " s.add_dependency(%q<#{dep.name}>, #{version_reqs_param})"
  586. end
  587. result << ' end'
  588. result << " else"
  589. dependencies.each do |dep|
  590. version_reqs_param = dep.requirements_list.inspect
  591. result << " s.add_dependency(%q<#{dep.name}>, #{version_reqs_param})"
  592. end
  593. result << " end"
  594. result << "end"
  595. result << nil
  596. result.join "\n"
  597. end
  598. def to_ruby_for_cache
  599. for_cache.to_ruby
  600. end
  601. ##
  602. # Checks that the specification contains all required fields, and does a
  603. # very basic sanity check.
  604. #
  605. # Raises InvalidSpecificationException if the spec does not pass the
  606. # checks..
  607. def validate packaging = true
  608. require 'rubygems/user_interaction'
  609. extend Gem::UserInteraction
  610. normalize
  611. nil_attributes = self.class.non_nil_attributes.find_all do |name|
  612. instance_variable_get("@#{name}").nil?
  613. end
  614. unless nil_attributes.empty? then
  615. raise Gem::InvalidSpecificationException,
  616. "#{nil_attributes.join ', '} must not be nil"
  617. end
  618. if packaging and rubygems_version != Gem::VERSION then
  619. raise Gem::InvalidSpecificationException,
  620. "expected RubyGems version #{Gem::VERSION}, was #{rubygems_version}"
  621. end
  622. @@required_attributes.each do |symbol|
  623. unless self.send symbol then
  624. raise Gem::InvalidSpecificationException,
  625. "missing value for attribute #{symbol}"
  626. end
  627. end
  628. unless String === name then
  629. raise Gem::InvalidSpecificationException,
  630. "invalid value for attribute name: \"#{name.inspect}\""
  631. end
  632. if require_paths.empty? then
  633. raise Gem::InvalidSpecificationException,
  634. 'specification must have at least one require_path'
  635. end
  636. @files.delete_if do |file| File.directory? file end
  637. @test_files.delete_if do |file| File.directory? file end
  638. @executables.delete_if do |file|
  639. File.directory? File.join(bindir, file)
  640. end
  641. @extra_rdoc_files.delete_if do |file| File.directory? file end
  642. @extensions.delete_if do |file| File.directory? file end
  643. non_files = files.select do |file|
  644. !File.file? file
  645. end
  646. unless not packaging or non_files.empty? then
  647. non_files = non_files.map { |file| file.inspect }
  648. raise Gem::InvalidSpecificationException,
  649. "[#{non_files.join ", "}] are not files"
  650. end
  651. unless specification_version.is_a?(Fixnum)
  652. raise Gem::InvalidSpecificationException,
  653. 'specification_version must be a Fixnum (did you mean version?)'
  654. end
  655. case platform
  656. when Gem::Platform, Gem::Platform::RUBY then # ok
  657. else
  658. raise Gem::InvalidSpecificationException,
  659. "invalid platform #{platform.inspect}, see Gem::Platform"
  660. end
  661. self.class.array_attributes.each do |symbol|
  662. val = self.send symbol
  663. klass = symbol == :dependencies ? Gem::Dependency : String
  664. unless Array === val and val.all? { |x| klass === x } then
  665. raise(Gem::InvalidSpecificationException,
  666. "#{symbol} must be an Array of #{klass} instances")
  667. end
  668. end
  669. licenses.each { |license|
  670. if license.length > 64
  671. raise Gem::InvalidSpecificationException,
  672. "each license must be 64 characters or less"
  673. end
  674. }
  675. # reject lazy developers:
  676. lazy = '"FIxxxXME" or "TOxxxDO"'.gsub(/xxx/, '')
  677. unless authors.grep(/FI XME|TO DO/x).empty? then
  678. raise Gem::InvalidSpecificationException, "#{lazy} is not an author"
  679. end
  680. unless Array(email).grep(/FI XME|TO DO/x).empty? then
  681. raise Gem::InvalidSpecificationException, "#{lazy} is not an email"
  682. end
  683. if description =~ /FI XME|TO DO/x then
  684. raise Gem::InvalidSpecificationException, "#{lazy} is not a description"
  685. end
  686. if summary =~ /FI XME|TO DO/x then
  687. raise Gem::InvalidSpecificationException, "#{lazy} is not a summary"
  688. end
  689. if homepage and not homepage.empty? and
  690. homepage !~ /\A[a-z][a-z\d+.-]*:/i then
  691. raise Gem::InvalidSpecificationException,
  692. "\"#{homepage}\" is not a URI"
  693. end
  694. # Warnings
  695. %w[author description email homepage summary].each do |attribute|
  696. value = self.send attribute
  697. alert_warning "no #{attribute} specified" if value.nil? or value.empty?
  698. end
  699. if description == summary then
  700. alert_warning 'description and summary are identical'
  701. end
  702. # TODO: raise at some given date
  703. alert_warning "deprecated autorequire specified" if autorequire
  704. executables.each do |executable|
  705. executable_path = File.join bindir, executable
  706. shebang = File.read(executable_path, 2) == '#!'
  707. alert_warning "#{executable_path} is missing #! line" unless shebang
  708. end
  709. true
  710. end
  711. ##
  712. # Normalize the list of files so that:
  713. # * All file lists have redundancies removed.
  714. # * Files referenced in the extra_rdoc_files are included in the package
  715. # file list.
  716. def normalize
  717. if defined?(@extra_rdoc_files) and @extra_rdoc_files then
  718. @extra_rdoc_files.uniq!
  719. @files ||= []
  720. @files.concat(@extra_rdoc_files)
  721. end
  722. @files.uniq! if @files
  723. end
  724. ##
  725. # Return a list of all gems that have a dependency on this gemspec. The
  726. # list is structured with entries that conform to:
  727. #
  728. # [depending_gem, dependency, [list_of_gems_that_satisfy_dependency]]
  729. def dependent_gems
  730. out = []
  731. Gem.source_index.each do |name,gem|
  732. gem.dependencies.each do |dep|
  733. if self.satisfies_requirement?(dep) then
  734. sats = []
  735. find_all_satisfiers(dep) do |sat|
  736. sats << sat
  737. end
  738. out << [gem, dep, sats]
  739. end
  740. end
  741. end
  742. out
  743. end
  744. def to_s # :nodoc:
  745. "#<Gem::Specification name=#{@name} version=#{@version}>"
  746. end
  747. def pretty_print(q) # :nodoc:
  748. q.group 2, 'Gem::Specification.new do |s|', 'end' do
  749. q.breakable
  750. # REFACTOR: each_attr - use in to_yaml as well
  751. @@attributes.each do |attr_name|
  752. current_value = self.send attr_name
  753. if current_value != default_value(attr_name) or
  754. self.class.required_attribute? attr_name then
  755. q.text "s.#{attr_name} = "
  756. if attr_name == :date then
  757. current_value = current_value.utc
  758. q.text "Time.utc(#{current_value.year}, #{current_value.month}, #{current_value.day})"
  759. else
  760. q.pp current_value
  761. end
  762. q.breakable
  763. end
  764. end
  765. end
  766. end
  767. ##
  768. # Adds a dependency on gem +dependency+ with type +type+ that requires
  769. # +requirements+. Valid types are currently <tt>:runtime</tt> and
  770. # <tt>:development</tt>.
  771. def add_dependency_with_type(dependency, type, *requirements)
  772. requirements = if requirements.empty? then
  773. Gem::Requirement.default
  774. else
  775. requirements.flatten
  776. end
  777. unless dependency.respond_to?(:name) &&
  778. dependency.respond_to?(:version_requirements)
  779. dependency = Gem::Dependency.new(dependency, requirements, type)
  780. end
  781. dependencies << dependency
  782. end
  783. private :add_dependency_with_type
  784. ##
  785. # Finds all gems that satisfy +dep+
  786. def find_all_satisfiers(dep)
  787. Gem.source_index.each do |_, gem|
  788. yield gem if gem.satisfies_requirement? dep
  789. end
  790. end
  791. private :find_all_satisfiers
  792. ##
  793. # Return a string containing a Ruby code representation of the given
  794. # object.
  795. def ruby_code(obj)
  796. case obj
  797. when String then '%q{' + obj + '}'
  798. when Array then obj.inspect
  799. when Gem::Version then obj.to_s.inspect
  800. when Date then '%q{' + obj.strftime('%Y-%m-%d') + '}'
  801. when Time then '%q{' + obj.strftime('%Y-%m-%d') + '}'
  802. when Numeric then obj.inspect
  803. when true, false, nil then obj.inspect
  804. when Gem::Platform then "Gem::Platform.new(#{obj.to_a.inspect})"
  805. when Gem::Requirement then "Gem::Requirement.new(#{obj.to_s.inspect})"
  806. else raise Gem::Exception, "ruby_code case not handled: #{obj.class}"
  807. end
  808. end
  809. private :ruby_code
  810. # :section: Required gemspec attributes
  811. ##
  812. # The version of RubyGems used to create this gem.
  813. #
  814. # Do not set this, it is set automatically when the gem is packaged.
  815. attr_accessor :rubygems_version
  816. ##
  817. # The Gem::Specification version of this gemspec.
  818. #
  819. # Do not set this, it is set automatically when the gem is packaged.
  820. attr_accessor :specification_version
  821. ##
  822. # This gem's name
  823. attr_accessor :name
  824. ##
  825. # This gem's version
  826. attr_reader :version
  827. ##
  828. # A short summary of this gem's description. Displayed in `gem list -d`.
  829. #
  830. # The description should be more detailed than the summary. For example,
  831. # you might wish to copy the entire README into the description.
  832. #
  833. # As of RubyGems 1.3.2 newlines are no longer stripped.
  834. attr_reader :summary
  835. ##
  836. # Paths in the gem to add to $LOAD_PATH when this gem is activated.
  837. #
  838. # The default 'lib' is typically sufficient.
  839. attr_accessor :require_paths
  840. # :section: Optional gemspec attributes
  841. ##
  842. # A contact email for this gem
  843. #
  844. # If you are providing multiple authors and multiple emails they should be
  845. # in the same order such that:
  846. #
  847. # Hash[*spec.authors.zip(spec.emails).flatten]
  848. #
  849. # Gives a hash of author name to email address.
  850. attr_accessor :email
  851. ##
  852. # The URL of this gem's home page
  853. attr_accessor :homepage
  854. ##
  855. # The rubyforge project this gem lives under. i.e. RubyGems'
  856. # rubyforge_project is "rubygems".
  857. attr_accessor :rubyforge_project
  858. ##
  859. # A long description of this gem
  860. attr_reader :description
  861. ##
  862. # Autorequire was used by old RubyGems to automatically require a file.
  863. # It no longer is supported.
  864. attr_accessor :autorequire
  865. ##
  866. # The default executable for this gem.
  867. attr_writer :default_executable
  868. ##
  869. # The path in the gem for executable scripts
  870. attr_accessor :bindir
  871. ##
  872. # The version of ruby required by this gem
  873. attr_reader :required_ruby_version
  874. ##
  875. # The RubyGems version required by this gem
  876. attr_reader :required_rubygems_version
  877. ##
  878. # The key used to sign this gem. See Gem::Security for details.
  879. attr_accessor :signing_key
  880. ##
  881. # The certificate chain used to sign this gem. See Gem::Security for
  882. # details.
  883. attr_accessor :cert_chain
  884. ##
  885. # A message that gets displayed after the gem is installed
  886. attr_accessor :post_install_message
  887. ##
  888. # The list of author names who wrote this gem.
  889. #
  890. # If you are providing multiple authors and multiple emails they should be
  891. # in the same order such that:
  892. #
  893. # Hash[*spec.authors.zip(spec.emails).flatten]
  894. #
  895. # Gives a hash of author name to email address.
  896. def authors
  897. @authors ||= []
  898. end
  899. def authors=(value)
  900. @authors = Array(value)
  901. end
  902. ##
  903. # The license(s) for the library. Each license must be a short name, no
  904. # more than 64 characters.
  905. def licenses
  906. @licenses ||= []
  907. end
  908. def licenses=(value)
  909. @licenses = Array(value)
  910. end
  911. ##
  912. # Files included in this gem. You cannot append to this accessor, you must
  913. # assign to it.
  914. #
  915. # Only add files you can require to this list, not directories, etc.
  916. #
  917. # Directories are automatically stripped from this list when building a gem,
  918. # other non-files cause an error.
  919. def files
  920. @files ||= []
  921. end
  922. def files=(value)
  923. @files = Array(value)
  924. end
  925. ##
  926. # Test files included in this gem. You cannot append to this accessor, you
  927. # must assign to it.
  928. def test_files
  929. @test_files ||= []
  930. end
  931. def test_files=(value)
  932. @test_files = Array(value)
  933. end
  934. ##
  935. # An ARGV style array of options to RDoc
  936. def rdoc_options
  937. @rdoc_options ||= []
  938. end
  939. def rdoc_options=(value)
  940. # TODO: warn about setting instead of pushing
  941. @rdoc_options = Array(value)
  942. end
  943. ##
  944. # Extra files to add to RDoc such as README or doc/examples.txt
  945. def extra_rdoc_files
  946. @extra_rdoc_files ||= []
  947. end
  948. def extra_rdoc_files=(value)
  949. # TODO: warn about setting instead of pushing
  950. @extra_rdoc_files = Array(value)
  951. end
  952. ##
  953. # Executables included in the gem.
  954. def executables
  955. @executables ||= []
  956. end
  957. def executables=(value)
  958. # TODO: warn about setting instead of pushing
  959. @executables = Array(value)
  960. end
  961. ##
  962. # Extensions to build when installing the gem. See
  963. # Gem::Installer#build_extensions for valid values.
  964. def extensions
  965. @extensions ||= []
  966. end
  967. def extensions=(value)
  968. # TODO: warn about setting instead of pushing
  969. @extensions = Array(value)
  970. end
  971. ##
  972. # An array or things required by this gem. Not used by anything
  973. # presently.
  974. def requirements
  975. @requirements ||= []
  976. end
  977. def requirements=(value)
  978. # TODO: warn about setting instead of pushing
  979. @requirements = Array(value)
  980. end
  981. ##
  982. # A list of Gem::Dependency objects this gem depends on.
  983. #
  984. # Use #add_dependency or #add_development_dependency to add dependencies to
  985. # a gem.
  986. def dependencies
  987. @dependencies ||= []
  988. end
  989. # :section: Aliased gemspec attributes
  990. ##
  991. # Singular accessor for #executables
  992. def executable
  993. val = executables and val.first
  994. end
  995. ##
  996. # Singular accessor for #executables
  997. def executable=o
  998. self.executables = [o]
  999. end
  1000. ##
  1001. # Singular accessor for #authors
  1002. def author
  1003. val = authors and val.first
  1004. end
  1005. ##
  1006. # Singular accessor for #authors
  1007. def author=o
  1008. self.authors = [o]
  1009. end
  1010. ##
  1011. # Singular accessor for #licenses
  1012. def license
  1013. val = licenses and val.first
  1014. end
  1015. ##
  1016. # Singular accessor for #licenses
  1017. def license=o
  1018. self.licenses = [o]
  1019. end
  1020. ##
  1021. # Singular accessor for #require_paths
  1022. def require_path
  1023. val = require_paths and val.first
  1024. end
  1025. ##
  1026. # Singular accessor for #require_paths
  1027. def require_path=o
  1028. self.require_paths = [o]
  1029. end
  1030. ##
  1031. # Singular accessor for #test_files
  1032. def test_file
  1033. val = test_files and val.first
  1034. end
  1035. ##
  1036. # Singular accessor for #test_files
  1037. def test_file=o
  1038. self.test_files = [o]
  1039. end
  1040. ##
  1041. # Deprecated and ignored, defaults to true.
  1042. #
  1043. # Formerly used to indicate this gem was RDoc-capable.
  1044. def has_rdoc
  1045. true
  1046. end
  1047. ##
  1048. # Deprecated and ignored.
  1049. #
  1050. # Formerly used to indicate this gem was RDoc-capable.
  1051. def has_rdoc= v
  1052. @has_rdoc = true
  1053. end
  1054. alias :has_rdoc? :has_rdoc
  1055. def version= version
  1056. @version = Gem::Version.create(version)
  1057. self.required_rubygems_version = '> 1.3.1' if @version.prerelease?
  1058. return @version
  1059. end
  1060. ##
  1061. # The platform this gem runs on. See Gem::Platform for details.
  1062. def platform
  1063. @new_platform
  1064. end
  1065. ##
  1066. # The platform this gem runs on. See Gem::Platform for details.
  1067. #
  1068. # Setting this to any value other than Gem::Platform::RUBY or
  1069. # Gem::Platform::CURRENT is probably wrong.
  1070. def platform= platform
  1071. if @original_platform.nil? or
  1072. @original_platform == Gem::Platform::RUBY then
  1073. @original_platform = platform
  1074. end
  1075. case platform
  1076. when Gem::Platform::CURRENT then
  1077. @new_platform = Gem::Platform.local
  1078. @original_platform = @new_platform.to_s
  1079. when Gem::Platform then
  1080. @new_platform = platform
  1081. # legacy constants
  1082. when nil, Gem::Platform::RUBY then
  1083. @new_platform = Gem::Platform::RUBY
  1084. when 'mswin32' then # was Gem::Platform::WIN32
  1085. @new_platform = Gem::Platform.new 'x86-mswin32'
  1086. when 'i586-linux' then # was Gem::Platform::LINUX_586
  1087. @new_platform = Gem::Platform.new 'x86-linux'
  1088. when 'powerpc-darwin' then # was Gem::Platform::DARWIN
  1089. @new_platform = Gem::Platform.new 'ppc-darwin'
  1090. else
  1091. @new_platform = Gem::Platform.new platform
  1092. end
  1093. @platform = @new_platform.to_s
  1094. @new_platform
  1095. end
  1096. ##
  1097. # The version of ruby required by this gem
  1098. def required_ruby_version= value
  1099. @required_ruby_version = Gem::Requirement.create(value)
  1100. end
  1101. ##
  1102. # The RubyGems version required by this gem
  1103. def required_rubygems_version= value
  1104. @required_rubygems_version = Gem::Requirement.create(value)
  1105. end
  1106. ##
  1107. # The date this gem was created
  1108. #
  1109. # Do not set this, it is set automatically when the gem is packaged.
  1110. def date= date
  1111. # We want to end up with a Time object with one-day resolution.
  1112. # This is the cleanest, most-readable, faster-than-using-Date
  1113. # way to do it.
  1114. @date = case date
  1115. when String then
  1116. if /\A(\d{4})-(\d{2})-(\d{2})\Z/ =~ date then
  1117. Time.utc($1.to_i, $2.to_i, $3.to_i)
  1118. else
  1119. raise(Gem::InvalidSpecificationException,
  1120. "invalid date format in specification: #{date.inspect}")
  1121. end
  1122. when Time, Date then
  1123. Time.utc(date.year, date.month, date.day)
  1124. else
  1125. TODAY
  1126. end
  1127. end
  1128. ##
  1129. # The date this gem was created. Lazily defaults to TODAY.
  1130. def date
  1131. @date ||= TODAY
  1132. end
  1133. ##
  1134. # A short summary of this gem's description.
  1135. def summary= str
  1136. @summary = str.to_s.strip.
  1137. gsub(/(\w-)\n[ \t]*(\w)/, '\1\2').gsub(/\n[ \t]*/, " ") # so. weird.
  1138. end
  1139. ##
  1140. # A long description of this gem
  1141. def description= str
  1142. @description = str.to_s
  1143. end
  1144. ##
  1145. # The default executable for this gem.
  1146. def default_executable
  1147. if defined?(@default_executable) and @default_executable
  1148. result = @default_executable
  1149. elsif @executables and @executables.size == 1
  1150. result = Array(@executables).first
  1151. else
  1152. result = nil
  1153. end
  1154. result
  1155. end
  1156. undef_method :test_files
  1157. def test_files
  1158. # Handle the possibility that we have @test_suite_file but not
  1159. # @test_files. This will happen when an old gem is loaded via
  1160. # YAML.
  1161. if defined? @test_suite_file then
  1162. @test_files = [@test_suite_file].flatten
  1163. @test_suite_file = nil
  1164. end
  1165. if defined?(@test_files) and @test_files then
  1166. @test_files
  1167. else
  1168. @test_files = []
  1169. end
  1170. end
  1171. undef_method :files
  1172. def files
  1173. # DO NOT CHANGE TO ||= ! This is not a normal accessor. (yes, it sucks)
  1174. @files = [@files,
  1175. @test_files,
  1176. add_bindir(@executables),
  1177. @extra_rdoc_files,
  1178. @extensions,
  1179. ].flatten.uniq.compact
  1180. end
  1181. def conflicts
  1182. conflicts = {}
  1183. Gem.loaded_specs.values.each do |spec|
  1184. bad = self.runtime_dependencies.find_all { |dep|
  1185. spec.name == dep.name and not spec.satisfies_requirement? dep
  1186. }
  1187. conflicts[spec] = bad unless bad.empty?
  1188. end
  1189. conflicts
  1190. end
  1191. def traverse trail = [], &b
  1192. trail = trail + [self]
  1193. runtime_dependencies.each do |dep|
  1194. dep_specs = Gem.source_index.search dep, true
  1195. dep_specs.each do |dep_spec|
  1196. b[self, dep, dep_spec, trail + [dep_spec]]
  1197. dep_spec.traverse(trail, &b) unless
  1198. trail.map(&:name).include? dep_spec.name
  1199. end
  1200. end
  1201. end
  1202. def dependent_specs
  1203. runtime_dependencies.map { |dep| Gem.source_index.search dep, true }.flatten
  1204. end
  1205. extend Deprecate
  1206. deprecate :test_suite_file, :test_file, 2011, 10
  1207. deprecate :test_suite_file=, :test_file=, 2011, 10
  1208. deprecate :has_rdoc, :none, 2011, 10
  1209. deprecate :has_rdoc?, :none, 2011, 10
  1210. deprecate :has_rdoc=, :none, 2011, 10
  1211. deprecate :default_executable, :none, 2011, 10
  1212. deprecate :default_executable=, :none, 2011, 10
  1213. end