/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

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