PageRenderTime 60ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/Languages/Ruby/StdLib/ruby/1.9.1/rubygems/specification.rb

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