PageRenderTime 113ms CodeModel.GetById 44ms app.highlight 24ms RepoModel.GetById 42ms app.codeStats 0ms

/tools/Ruby/lib/ruby/site_ruby/1.8/rubygems/commands/query_command.rb

http://github.com/agross/netopenspace
Ruby | 260 lines | 203 code | 55 blank | 2 comment | 27 complexity | 510405e519116ee1b78c50f5ad208005 MD5 | raw file
  1require 'rubygems/command'
  2require 'rubygems/local_remote_options'
  3require 'rubygems/spec_fetcher'
  4require 'rubygems/version_option'
  5require 'rubygems/text'
  6
  7class Gem::Commands::QueryCommand < Gem::Command
  8
  9  include Gem::Text
 10  include Gem::LocalRemoteOptions
 11  include Gem::VersionOption
 12
 13  def initialize(name = 'query',
 14                 summary = 'Query gem information in local or remote repositories')
 15    super name, summary,
 16         :name => //, :domain => :local, :details => false, :versions => true,
 17         :installed => false, :version => Gem::Requirement.default
 18
 19    add_option('-i', '--[no-]installed',
 20               'Check for installed gem') do |value, options|
 21      options[:installed] = value
 22    end
 23
 24    add_version_option command, "for use with --installed"
 25
 26    add_option('-n', '--name-matches REGEXP',
 27               'Name of gem(s) to query on matches the',
 28               'provided REGEXP') do |value, options|
 29      options[:name] = /#{value}/i
 30    end
 31
 32    add_option('-d', '--[no-]details',
 33               'Display detailed information of gem(s)') do |value, options|
 34      options[:details] = value
 35    end
 36
 37    add_option(      '--[no-]versions',
 38               'Display only gem names') do |value, options|
 39      options[:versions] = value
 40      options[:details] = false unless value
 41    end
 42
 43    add_option('-a', '--all',
 44               'Display all gem versions') do |value, options|
 45      options[:all] = value
 46    end
 47
 48    add_option(      '--[no-]prerelease',
 49               'Display prerelease versions') do |value, options|
 50      options[:prerelease] = value
 51    end
 52
 53    add_local_remote_options
 54  end
 55
 56  def defaults_str # :nodoc:
 57    "--local --name-matches // --no-details --versions --no-installed"
 58  end
 59
 60  def execute
 61    exit_code = 0
 62
 63    name = options[:name]
 64    prerelease = options[:prerelease]
 65
 66    if options[:installed] then
 67      if name.source.empty? then
 68        alert_error "You must specify a gem name"
 69        exit_code |= 4
 70      elsif installed? name, options[:version] then
 71        say "true"
 72      else
 73        say "false"
 74        exit_code |= 1
 75      end
 76
 77      raise Gem::SystemExitException, exit_code
 78    end
 79
 80    dep = Gem::Dependency.new name, Gem::Requirement.default
 81
 82    if local? then
 83      if prerelease and not both? then
 84        alert_warning "prereleases are always shown locally"
 85      end
 86
 87      if ui.outs.tty? or both? then
 88        say
 89        say "*** LOCAL GEMS ***"
 90        say
 91      end
 92
 93      specs = Gem.source_index.search dep
 94
 95      spec_tuples = specs.map do |spec|
 96        [[spec.name, spec.version, spec.original_platform, spec], :local]
 97      end
 98
 99      output_query_results spec_tuples
100    end
101
102    if remote? then
103      if ui.outs.tty? or both? then
104        say
105        say "*** REMOTE GEMS ***"
106        say
107      end
108
109      all = options[:all]
110
111      fetcher = Gem::SpecFetcher.fetcher
112      spec_tuples = fetcher.find_matching dep, all, false, prerelease
113
114      spec_tuples += fetcher.find_matching dep, false, false, true if
115        prerelease and all
116
117      output_query_results spec_tuples
118    end
119  end
120
121  private
122
123  ##
124  # Check if gem +name+ version +version+ is installed.
125
126  def installed?(name, version = Gem::Requirement.default)
127    dep = Gem::Dependency.new name, version
128    !Gem.source_index.search(dep).empty?
129  end
130
131  def output_query_results(spec_tuples)
132    output = []
133    versions = Hash.new { |h,name| h[name] = [] }
134
135    spec_tuples.each do |spec_tuple, source_uri|
136      versions[spec_tuple.first] << [spec_tuple, source_uri]
137    end
138
139    versions = versions.sort_by do |(name,_),_|
140      name.downcase
141    end
142
143    versions.each do |gem_name, matching_tuples|
144      matching_tuples = matching_tuples.sort_by do |(_, version,_),_|
145        version
146      end.reverse
147
148      platforms = Hash.new { |h,version| h[version] = [] }
149
150      matching_tuples.map do |(_, version, platform,_),_|
151        platforms[version] << platform if platform
152      end
153
154      seen = {}
155
156      matching_tuples.delete_if do |(_, version,_),_|
157        if seen[version] then
158          true
159        else
160          seen[version] = true
161          false
162        end
163      end
164
165      entry = gem_name.dup
166
167      if options[:versions] then
168        list = if platforms.empty? or options[:details] then
169                 matching_tuples.map { |(_, version,_),_| version }.uniq
170               else
171                 platforms.sort.reverse.map do |version, pls|
172                   if pls == [Gem::Platform::RUBY] then
173                     version
174                   else
175                     ruby = pls.delete Gem::Platform::RUBY
176                     platform_list = [ruby, *pls.sort].compact
177                     "#{version} #{platform_list.join ' '}"
178                   end
179                 end
180               end.join ', '
181
182        entry << " (#{list})"
183      end
184
185      if options[:details] then
186        detail_tuple = matching_tuples.first
187
188        spec = if detail_tuple.first.length == 4 then
189                 detail_tuple.first.last
190               else
191                 uri = URI.parse detail_tuple.last
192                 Gem::SpecFetcher.fetcher.fetch_spec detail_tuple.first, uri
193               end
194
195        entry << "\n"
196
197        non_ruby = platforms.any? do |_, pls|
198          pls.any? { |pl| pl != Gem::Platform::RUBY }
199        end
200
201        if non_ruby then
202          if platforms.length == 1 then
203            title = platforms.values.length == 1 ? 'Platform' : 'Platforms'
204            entry << "    #{title}: #{platforms.values.sort.join ', '}\n"
205          else
206            entry << "    Platforms:\n"
207            platforms.sort_by do |version,|
208              version
209            end.each do |version, pls|
210              label = "        #{version}: "
211              data = format_text pls.sort.join(', '), 68, label.length
212              data[0, label.length] = label
213              entry << data << "\n"
214            end
215          end
216        end
217
218        authors = "Author#{spec.authors.length > 1 ? 's' : ''}: "
219        authors << spec.authors.join(', ')
220        entry << format_text(authors, 68, 4)
221
222        if spec.rubyforge_project and not spec.rubyforge_project.empty? then
223          rubyforge = "Rubyforge: http://rubyforge.org/projects/#{spec.rubyforge_project}"
224          entry << "\n" << format_text(rubyforge, 68, 4)
225        end
226
227        if spec.homepage and not spec.homepage.empty? then
228          entry << "\n" << format_text("Homepage: #{spec.homepage}", 68, 4)
229        end
230
231        if spec.license and not spec.license.empty? then
232          licenses = "License#{spec.licenses.length > 1 ? 's' : ''}: "
233          licenses << spec.licenses.join(', ')
234          entry << "\n" << format_text(licenses, 68, 4)
235        end
236
237        if spec.loaded_from then
238          if matching_tuples.length == 1 then
239            loaded_from = File.dirname File.dirname(spec.loaded_from)
240            entry << "\n" << "    Installed at: #{loaded_from}"
241          else
242            label = 'Installed at'
243            matching_tuples.each do |(_,version,_,s),|
244              loaded_from = File.dirname File.dirname(s.loaded_from)
245              entry << "\n" << "    #{label} (#{version}): #{loaded_from}"
246              label = ' ' * label.length
247            end
248          end
249        end
250
251        entry << "\n\n" << format_text(spec.summary, 68, 4)
252      end
253      output << entry
254    end
255
256    say output.join(options[:details] ? "\n\n" : "\n")
257  end
258
259end
260