diff options
Diffstat (limited to 'railties/lib/rails/vendor_gem_source_index.rb')
-rw-r--r-- | railties/lib/rails/vendor_gem_source_index.rb | 83 |
1 files changed, 64 insertions, 19 deletions
diff --git a/railties/lib/rails/vendor_gem_source_index.rb b/railties/lib/rails/vendor_gem_source_index.rb index e188f07895..0dac1d5394 100644 --- a/railties/lib/rails/vendor_gem_source_index.rb +++ b/railties/lib/rails/vendor_gem_source_index.rb @@ -13,6 +13,14 @@ module Rails attr_reader :installed_source_index attr_reader :vendor_source_index + def self.silence_spec_warnings + @@silence_spec_warnings + end + + def self.silence_spec_warnings=(v) + @@silence_spec_warnings = v + end + def initialize(installed_index, vendor_dir=Rails::GemDependency.unpacked_path) @installed_source_index = installed_index @vendor_dir = vendor_dir @@ -33,31 +41,68 @@ module Rails # load specifications from vendor/gems Dir[File.join(Rails::GemDependency.unpacked_path, '*')].each do |d| + dir_name = File.basename(d) + dir_version = version_for_dir(dir_name) 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') + if spec + if spec.full_name != dir_name + # mismatched directory name and gem spec - produced by 2.1.0-era unpack code + if dir_version + # fix the spec version - this is not optimal (spec.files may be wrong) + # but it's better than breaking apps. Complain to remind users to get correct specs. + # use ActiveSupport::Deprecation.warn, as the logger is not set yet + $stderr.puts("config.gem: Unpacked gem #{dir_name} in vendor/gems has a mismatched specification file."+ + " Run 'rake gems:refresh_specs' to fix this.") unless @@silence_spec_warnings + spec.version = dir_version + else + $stderr.puts("config.gem: Unpacked gem #{dir_name} in vendor/gems is not in a versioned directory"+ + "(should be #{spec.full_name}).") unless @@silence_spec_warnings + # continue, assume everything is OK + end + end + else + # no spec - produced by early-2008 unpack code + # emulate old behavior, and complain. + $stderr.puts("config.gem: Unpacked gem #{dir_name} in vendor/gems has no specification file."+ + " Run 'rake gems:refresh_specs' to fix this.") unless @@silence_spec_warnings + if dir_version + spec = Gem::Specification.new + spec.version = dir_version + spec.require_paths = ['lib'] + ext_path = File.join(d, 'ext') + spec.require_paths << 'ext' if File.exist?(ext_path) + spec.name = /^(.*)-[^-]+$/.match(dir_name)[1] + files = ['lib'] + # set files to everything in lib/ + files += Dir[File.join(d, 'lib', '*')].map { |v| v.gsub(/^#{d}\//, '') } + files += Dir[File.join(d, 'ext', '*')].map { |v| v.gsub(/^#{d}\//, '') } if ext_path + spec.files = files + else + $stderr.puts("config.gem: Unpacked gem #{dir_name} in vendor/gems not in a versioned directory."+ + " Giving up.") unless @silence_spec_warnings + next + end + end + spec.loaded_from = File.join(d, '.specification') + # finally, swap out full_gem_path + # it would be better to use a Gem::Specification subclass, but the YAML loads an explicit class + class << spec + def full_gem_path + path = File.join installation_path, full_name + return path if File.directory? path + File.join installation_path, original_name + end + end vendor_gems[File.basename(d)] = spec end @vendor_source_index = Gem::SourceIndex.new(vendor_gems) end + def version_for_dir(d) + matches = /-([^-]+)$/.match(d) + Gem::Version.new(matches[1]) if matches + end + def load_specification(gem_dir) spec_file = File.join(gem_dir, '.specification') YAML.load_file(spec_file) if File.exist?(spec_file) |