1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
|
require 'rubygems/command'
require 'rubygems/local_remote_options'
require 'rubygems/version_option'
class Gem::Commands::DependencyCommand < Gem::Command
include Gem::LocalRemoteOptions
include Gem::VersionOption
def initialize
super 'dependency',
'Show the dependencies of an installed gem',
:version => Gem::Requirement.default, :domain => :local
add_version_option
add_platform_option
add_prerelease_option
add_option('-R', '--[no-]reverse-dependencies',
'Include reverse dependencies in the output') do
|value, options|
options[:reverse_dependencies] = value
end
add_option('-p', '--pipe',
"Pipe Format (name --version ver)") do |value, options|
options[:pipe_format] = value
end
add_local_remote_options
end
def arguments # :nodoc:
"REGEXP show dependencies for gems whose names start with REGEXP"
end
def defaults_str # :nodoc:
"--local --version '#{Gem::Requirement.default}' --no-reverse-dependencies"
end
def description # :nodoc:
<<-EOF
The dependency commands lists which other gems a given gem depends on. For
local gems only the reverse dependencies can be shown (which gems depend on
the named gem).
The dependency list can be displayed in a format suitable for piping for
use with other commands.
EOF
end
def usage # :nodoc:
"#{program_name} REGEXP"
end
def fetch_remote_specs dependency # :nodoc:
fetcher = Gem::SpecFetcher.fetcher
ss, = fetcher.spec_for_dependency dependency
ss.map { |spec, _| spec }
end
def fetch_specs dependency # :nodoc:
specs = []
specs.concat dependency.matching_specs if local?
specs.concat fetch_remote_specs dependency if remote?
ensure_specs specs
specs.uniq.sort
end
def gem_dependency args, version, prerelease # :nodoc:
args << '' if args.empty?
pattern = if args.length == 1 and args.first =~ /\A\/(.*)\/(i)?\z/m then
flags = $2 ? Regexp::IGNORECASE : nil
Regexp.new $1, flags
else
/\A#{Regexp.union(*args)}/
end
dependency = Gem::Deprecate.skip_during {
Gem::Dependency.new pattern, version
}
dependency.prerelease = prerelease
dependency
end
def display_pipe specs # :nodoc:
specs.each do |spec|
unless spec.dependencies.empty? then
spec.dependencies.sort_by { |dep| dep.name }.each do |dep|
say "#{dep.name} --version '#{dep.requirement}'"
end
end
end
end
def display_readable specs, reverse # :nodoc:
response = ''
specs.each do |spec|
response << print_dependencies(spec)
unless reverse[spec.full_name].empty? then
response << " Used by\n"
reverse[spec.full_name].each do |sp, dep|
response << " #{sp} (#{dep})\n"
end
end
response << "\n"
end
say response
end
def execute
ensure_local_only_reverse_dependencies
dependency =
gem_dependency options[:args], options[:version], options[:prerelease]
specs = fetch_specs dependency
reverse = reverse_dependencies specs
if options[:pipe_format] then
display_pipe specs
else
display_readable specs, reverse
end
end
def ensure_local_only_reverse_dependencies # :nodoc:
if options[:reverse_dependencies] and remote? and not local? then
alert_error 'Only reverse dependencies for local gems are supported.'
terminate_interaction 1
end
end
def ensure_specs specs # :nodoc:
return unless specs.empty?
patterns = options[:args].join ','
say "No gems found matching #{patterns} (#{options[:version]})" if
Gem.configuration.verbose
terminate_interaction 1
end
def print_dependencies(spec, level = 0) # :nodoc:
response = ''
response << ' ' * level + "Gem #{spec.full_name}\n"
unless spec.dependencies.empty? then
spec.dependencies.sort_by { |dep| dep.name }.each do |dep|
response << ' ' * level + " #{dep}\n"
end
end
response
end
def remote_specs dependency # :nodoc:
fetcher = Gem::SpecFetcher.fetcher
ss, _ = fetcher.spec_for_dependency dependency
ss.map { |s,o| s }
end
def reverse_dependencies specs # :nodoc:
reverse = Hash.new { |h, k| h[k] = [] }
return reverse unless options[:reverse_dependencies]
specs.each do |spec|
reverse[spec.full_name] = find_reverse_dependencies spec
end
reverse
end
##
# Returns an Array of [specification, dep] that are satisfied by +spec+.
def find_reverse_dependencies spec # :nodoc:
result = []
Gem::Specification.each do |sp|
sp.dependencies.each do |dep|
dep = Gem::Dependency.new(*dep) unless Gem::Dependency === dep
if spec.name == dep.name and
dep.requirement.satisfied_by?(spec.version) then
result << [sp.full_name, dep]
end
end
end
result
end
end
|