1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00
rails--rails/railties/lib/rails/vendor_gem_source_index.rb
Matt Jones 2bf58aa782 Fix a number of errors in the config.gem mechanism.
* Rails::GemDependency was missing definitions for hash and eql?, causing Array#uniq to not work.

* If several versions of a gem are unpacked in vendor, now chooses the highest if no version is specified.

* streamlined add_load_path. Now sets up Rubygems correctly to allow 'gem' to find frozen gems, with
  gems frozen to vendor/gems and specifications in vendor/gems/<gem-name>/.specification

* Rails::GemDependency#specification would return a spec for the highest installed version, even for
  frozen gems and/or previously loaded lower versions. See in part ticket #1123.

* removed vendor from default_load_paths - it was causing autoloading to append Gems::Gems::<gem-dir> to
  constant names

* added additional tests for loading frozen gems.

* incorporates the fix from #1107 for vendor rails

* defers to freeze:gems for handling the Rails framework. gems:unpack WILL NOT place a copy of Rails
  in vendor/gems. Should close #1123 completely.

* incorporates, via using the gem loader for frozen gems, fixes corresponding to #227, #324, #362, #527, and #742.

* gem plugins now work the same whether frozen or not. Correctness of the behavior is a matter for another ticket...

Signed-off-by: rick <technoweenie@gmail.com>
2008-10-05 10:16:17 -07:00

93 lines
No EOL
3 KiB
Ruby

require 'rubygems'
require 'yaml'
module Rails
class VendorGemSourceIndex
# VendorGemSourceIndex acts as a proxy for the Gem source index, allowing
# gems to be loaded from vendor/gems. Rather than the standard gem repository format,
# vendor/gems contains unpacked gems, with YAML specifications in .specification in
# each gem directory.
include Enumerable
attr_reader :installed_source_index
attr_reader :vendor_source_index
def initialize(installed_index, vendor_dir=Rails::GemDependency.unpacked_path)
@installed_source_index = installed_index
@vendor_dir = vendor_dir
refresh!
end
def refresh!
# reload the installed gems
@installed_source_index.refresh!
vendor_gems = {}
# handle vendor Rails gems - they are identified by having loaded_from set to ""
# we add them manually to the list, so that other gems can find them via dependencies
Gem.loaded_specs.each do |n, s|
next unless s.loaded_from.empty?
vendor_gems[s.full_name] = s
end
# load specifications from vendor/gems
Dir[File.join(Rails::GemDependency.unpacked_path, '*')].each do |d|
spec = load_specification(d)
next unless spec
# NOTE: this is a bit of a hack - the gem system expects a different structure
# than we have.
# It's looking for:
# repository
# -> specifications
# - gem_name.spec <= loaded_from points to this
# -> gems
# - gem_name <= gem files here
# and therefore goes up one directory from loaded_from, then adds gems/gem_name
# to the path.
# But we have:
# vendor
# -> gems
# -> gem_name <= gem files here
# - .specification
# so we set loaded_from to vendor/gems/.specification (not a real file) to
# get the correct behavior.
spec.loaded_from = File.join(Rails::GemDependency.unpacked_path, '.specification')
vendor_gems[File.basename(d)] = spec
end
@vendor_source_index = Gem::SourceIndex.new(vendor_gems)
end
def load_specification(gem_dir)
spec_file = File.join(gem_dir, '.specification')
YAML.load_file(spec_file) if File.exist?(spec_file)
end
def find_name(gem_name, version_requirement = Gem::Requirement.default)
search(/^#{gem_name}$/, version_requirement)
end
def search(*args)
# look for vendor gems, and then installed gems - later elements take priority
@installed_source_index.search(*args) + @vendor_source_index.search(*args)
end
def each(&block)
@vendor_source_index.each(&block)
@installed_source_index.each(&block)
end
def add_spec(spec)
@vendor_source_index.add_spec spec
end
def remove_spec(spec)
@vendor_source_index.remove_spec spec
end
def size
@vendor_source_index.size + @installed_source_index.size
end
end
end