Object
Installs a gem along with all its dependencies from local and remote gems.
Creates a new installer instance.
Options are:
:cache_dir | Alternate repository path to store .gem files in. |
:domain | :local, :remote, or :both. :local only searches gems in the current directory. :remote searches only gems in Gem::sources. :both searches both. |
:env_shebang | See Gem::Installer::new. |
:force | |
:format_executable | See Gem::Installer#initialize. |
:ignore_dependencies | Don’t install any dependencies. |
:install_dir | |
:prerelease | Allow prerelease versions. See #. |
:security_policy | See Gem::Installer::new and Gem::Security. |
:user_install | See Gem::Installer.new |
:wrappers |
# File lib/rubygems/dependency_installer.rb, line 46 46: def initialize(options = {}) 47: if options[:install_dir] then 48: @gem_home = options[:install_dir] 49: 50: Gem::Specification.dirs = @gem_home 51: Gem.ensure_gem_subdirectories @gem_home 52: options[:install_dir] = @gem_home # FIX: because we suck and reuse below 53: end 54: 55: options = DEFAULT_OPTIONS.merge options 56: 57: @bin_dir = options[:bin_dir] 58: @development = options[:development] 59: @domain = options[:domain] 60: @env_shebang = options[:env_shebang] 61: @force = options[:force] 62: @format_executable = options[:format_executable] 63: @ignore_dependencies = options[:ignore_dependencies] 64: @prerelease = options[:prerelease] 65: @security_policy = options[:security_policy] 66: @user_install = options[:user_install] 67: @wrappers = options[:wrappers] 68: 69: @installed_gems = [] 70: 71: @install_dir = options[:install_dir] || Gem.dir 72: @cache_dir = options[:cache_dir] || @install_dir 73: 74: # Set with any errors that SpecFetcher finds while search through 75: # gemspecs for a dep 76: @errors = nil 77: end
# File lib/rubygems/dependency_installer.rb, line 159 159: def add_found_dependencies to_do, dependency_list 160: seen = {} 161: dependencies = Hash.new { |h, name| h[name] = Gem::Dependency.new name } 162: 163: until to_do.empty? do 164: spec = to_do.shift 165: next if spec.nil? or seen[spec.name] 166: seen[spec.name] = true 167: 168: deps = spec.runtime_dependencies 169: deps |= spec.development_dependencies if @development 170: 171: deps.each do |dep| 172: dependencies[dep.name] = dependencies[dep.name].merge dep 173: 174: results = find_gems_with_sources(dep).reverse 175: 176: results.reject! do |dep_spec,| 177: to_do.push dep_spec 178: 179: # already locally installed 180: Gem::Specification.any? do |installed_spec| 181: dep.name == installed_spec.name and 182: dep.requirement.satisfied_by? installed_spec.version 183: end 184: end 185: 186: results.each do |dep_spec, source_uri| 187: @specs_and_sources << [dep_spec, source_uri] 188: 189: dependency_list.add dep_spec 190: end 191: end 192: end 193: 194: dependency_list.remove_specs_unsatisfied_by dependencies 195: end
Returns a list of pairs of gemspecs and source_uris that match Gem::Dependency dep from both local (Dir.pwd) and remote (Gem.sources) sources. Gems are sorted with newer gems preferred over older gems, and local gems preferred over remote gems.
# File lib/rubygems/dependency_installer.rb, line 85 85: def find_gems_with_sources(dep) 86: # Reset the errors 87: @errors = nil 88: gems_and_sources = [] 89: 90: if @domain == :both or @domain == :local then 91: Dir[File.join(Dir.pwd, "#{dep.name}-[0-9]*.gem")].each do |gem_file| 92: spec = Gem::Format.from_file_by_path(gem_file).spec 93: gems_and_sources << [spec, gem_file] if spec.name == dep.name 94: end 95: end 96: 97: if @domain == :both or @domain == :remote then 98: begin 99: # REFACTOR: all = dep.requirement.needs_all? 100: requirements = dep.requirement.requirements.map do |req, ver| 101: req 102: end 103: 104: all = !dep.prerelease? && 105: # we only need latest if there's one requirement and it is 106: # guaranteed to match the newest specs 107: (requirements.length > 1 or 108: (requirements.first != ">=" and requirements.first != ">")) 109: 110: found, @errors = Gem::SpecFetcher.fetcher.fetch_with_errors dep, all, true, dep.prerelease? 111: 112: gems_and_sources.push(*found) 113: 114: rescue Gem::RemoteFetcher::FetchError => e 115: if Gem.configuration.really_verbose then 116: say "Error fetching remote data:\t\t#{e.message}" 117: say "Falling back to local-only install" 118: end 119: @domain = :local 120: end 121: end 122: 123: gems_and_sources.sort_by do |gem, source| 124: [gem, source =~ /^http:\/\// ? 0 : 1] # local gems win 125: end 126: end
Finds a spec and the source_uri it came from for gem gem_name and version. Returns an Array of specs and sources required for installation of the gem.
# File lib/rubygems/dependency_installer.rb, line 202 202: def find_spec_by_name_and_version(gem_name, 203: version = Gem::Requirement.default, 204: prerelease = false) 205: spec_and_source = nil 206: 207: glob = if File::ALT_SEPARATOR then 208: gem_name.gsub File::ALT_SEPARATOR, File::SEPARATOR 209: else 210: gem_name 211: end 212: 213: local_gems = Dir["#{glob}*"].sort.reverse 214: 215: local_gems.each do |gem_file| 216: next unless gem_file =~ /gem$/ 217: begin 218: spec = Gem::Format.from_file_by_path(gem_file).spec 219: spec_and_source = [spec, gem_file] 220: break 221: rescue SystemCallError, Gem::Package::FormatError 222: end 223: end 224: 225: unless spec_and_source then 226: dep = Gem::Dependency.new gem_name, version 227: dep.prerelease = true if prerelease 228: spec_and_sources = find_gems_with_sources(dep).reverse 229: spec_and_source = spec_and_sources.find { |spec, source| 230: Gem::Platform.match spec.platform 231: } 232: end 233: 234: if spec_and_source.nil? then 235: raise Gem::GemNotFoundException.new( 236: "Could not find a valid gem '#{gem_name}' (#{version}) locally or in a repository", 237: gem_name, version, @errors) 238: end 239: 240: @specs_and_sources = [spec_and_source] 241: end
Gathers all dependencies necessary for the installation from local and remote sources unless the ignore_dependencies was given.
# File lib/rubygems/dependency_installer.rb, line 132 132: def gather_dependencies 133: specs = @specs_and_sources.map { |spec,_| spec } 134: 135: # these gems were listed by the user, always install them 136: keep_names = specs.map { |spec| spec.full_name } 137: 138: dependency_list = Gem::DependencyList.new @development 139: dependency_list.add(*specs) 140: to_do = specs.dup 141: 142: add_found_dependencies to_do, dependency_list unless @ignore_dependencies 143: 144: dependency_list.specs.reject! { |spec| 145: not keep_names.include?(spec.full_name) and 146: Gem::Specification.include?(spec) 147: } 148: 149: unless dependency_list.ok? or @ignore_dependencies or @force then 150: reason = dependency_list.why_not_ok?.map { |k,v| 151: "#{k} requires #{v.join(", ")}" 152: }.join("; ") 153: raise Gem::DependencyError, "Unable to resolve dependencies: #{reason}" 154: end 155: 156: @gems_to_install = dependency_list.dependency_order.reverse 157: end
Installs the gem dep_or_name and all its dependencies. Returns an Array of installed gem specifications.
If the :prerelease option is set and there is a prerelease for dep_or_name the prerelease version will be installed.
Unless explicitly specified as a prerelease dependency, prerelease gems that dep_or_name depend on will not be installed.
If c-1.a depends on b-1 and a-1.a and there is a gem b-1.a available then c-1.a, b-1 and a-1.a will be installed. b-1.a will need to be installed separately.
# File lib/rubygems/dependency_installer.rb, line 257 257: def install dep_or_name, version = Gem::Requirement.default 258: if String === dep_or_name then 259: find_spec_by_name_and_version dep_or_name, version, @prerelease 260: else 261: dep_or_name.prerelease = @prerelease 262: @specs_and_sources = [find_gems_with_sources(dep_or_name).last] 263: end 264: 265: @installed_gems = [] 266: 267: gather_dependencies 268: 269: last = @gems_to_install.size - 1 270: @gems_to_install.each_with_index do |spec, index| 271: next if Gem::Specification.include?(spec) and index != last 272: 273: # TODO: make this sorta_verbose so other users can benefit from it 274: say "Installing gem #{spec.full_name}" if Gem.configuration.really_verbose 275: 276: _, source_uri = @specs_and_sources.assoc spec 277: begin 278: local_gem_path = Gem::RemoteFetcher.fetcher.download spec, source_uri, 279: @cache_dir 280: rescue Gem::RemoteFetcher::FetchError 281: next if @force 282: raise 283: end 284: 285: inst = Gem::Installer.new local_gem_path, 286: :bin_dir => @bin_dir, 287: :development => @development, 288: :env_shebang => @env_shebang, 289: :force => @force, 290: :format_executable => @format_executable, 291: :ignore_dependencies => @ignore_dependencies, 292: :install_dir => @install_dir, 293: :security_policy => @security_policy, 294: :user_install => @user_install, 295: :wrappers => @wrappers 296: 297: spec = inst.install 298: 299: @installed_gems << spec 300: end 301: 302: @installed_gems 303: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.