diff options
Diffstat (limited to 'railties/lib/rails/vendor_gem_source_index.rb')
-rw-r--r-- | railties/lib/rails/vendor_gem_source_index.rb | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/railties/lib/rails/vendor_gem_source_index.rb b/railties/lib/rails/vendor_gem_source_index.rb new file mode 100644 index 0000000000..c8701101e2 --- /dev/null +++ b/railties/lib/rails/vendor_gem_source_index.rb @@ -0,0 +1,93 @@ +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
\ No newline at end of file |