1require 'rubygems/command'
2require 'rubygems/local_remote_options'
3require 'rubygems/version_option'
4require 'rubygems/package'
5
6class Gem::Commands::SpecificationCommand < Gem::Command
7
8  include Gem::LocalRemoteOptions
9  include Gem::VersionOption
10
11  def initialize
12    Gem.load_yaml
13
14    super 'specification', 'Display gem specification (in yaml)',
15          :domain => :local, :version => Gem::Requirement.default,
16          :format => :yaml
17
18    add_version_option('examine')
19    add_platform_option
20    add_prerelease_option
21
22    add_option('--all', 'Output specifications for all versions of',
23               'the gem') do |value, options|
24      options[:all] = true
25    end
26
27    add_option('--ruby', 'Output ruby format') do |value, options|
28      options[:format] = :ruby
29    end
30
31    add_option('--yaml', 'Output YAML format') do |value, options|
32      options[:format] = :yaml
33    end
34
35    add_option('--marshal', 'Output Marshal format') do |value, options|
36      options[:format] = :marshal
37    end
38
39    add_local_remote_options
40  end
41
42  def arguments # :nodoc:
43    <<-ARGS
44GEMFILE       name of gem to show the gemspec for
45FIELD         name of gemspec field to show
46    ARGS
47  end
48
49  def defaults_str # :nodoc:
50    "--local --version '#{Gem::Requirement.default}' --yaml"
51  end
52
53  def usage # :nodoc:
54    "#{program_name} [GEMFILE] [FIELD]"
55  end
56
57  def execute
58    specs = []
59    gem = options[:args].shift
60
61    unless gem then
62      raise Gem::CommandLineError,
63            "Please specify a gem name or file on the command line"
64    end
65
66    case v = options[:version]
67    when String
68      req = Gem::Requirement.create v
69    when Gem::Requirement
70      req = v
71    else
72      raise Gem::CommandLineError, "Unsupported version type: '#{v}'"
73    end
74
75    if !req.none? and options[:all]
76      alert_error "Specify --all or -v, not both"
77      terminate_interaction 1
78    end
79
80    if options[:all]
81      dep = Gem::Dependency.new gem
82    else
83      dep = Gem::Dependency.new gem, req
84    end
85
86    field = get_one_optional_argument
87
88    raise Gem::CommandLineError, "--ruby and FIELD are mutually exclusive" if
89      field and options[:format] == :ruby
90
91    if local? then
92      if File.exist? gem then
93        specs << Gem::Package.new(gem).spec rescue nil
94      end
95
96      if specs.empty? then
97        specs.push(*dep.matching_specs)
98      end
99    end
100
101    if remote? then
102      dep.prerelease = options[:prerelease]
103      found, _ = Gem::SpecFetcher.fetcher.spec_for_dependency dep
104
105      specs.push(*found.map { |spec,| spec })
106    end
107
108    if specs.empty? then
109      alert_error "No gem matching '#{dep}' found"
110      terminate_interaction 1
111    end
112
113    unless options[:all] then
114      specs = [specs.sort_by { |s| s.version }.last]
115    end
116
117    specs.each do |s|
118      s = s.send field if field
119
120      say case options[:format]
121          when :ruby then s.to_ruby
122          when :marshal then Marshal.dump s
123          else s.to_yaml
124          end
125
126      say "\n"
127    end
128  end
129end
130