~michaelforrest/use-case-mapper/trunk

« back to all changes in this revision

Viewing changes to vendor/rails/railties/lib/rails/vendor_gem_source_index.rb

  • Committer: Richard Lee (Canonical)
  • Date: 2010-10-15 15:17:58 UTC
  • mfrom: (190.1.3 use-case-mapper)
  • Revision ID: richard.lee@canonical.com-20101015151758-wcvmfxrexsongf9d
Merge

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
require 'rubygems'
2
 
require 'yaml'
3
 
 
4
 
module Rails
5
 
 
6
 
  class VendorGemSourceIndex
7
 
    # VendorGemSourceIndex acts as a proxy for the Gem source index, allowing
8
 
    # gems to be loaded from vendor/gems. Rather than the standard gem repository format,
9
 
    # vendor/gems contains unpacked gems, with YAML specifications in .specification in
10
 
    # each gem directory.
11
 
    include Enumerable
12
 
 
13
 
    attr_reader :installed_source_index
14
 
    attr_reader :vendor_source_index
15
 
 
16
 
    @@silence_spec_warnings = false
17
 
 
18
 
    def self.silence_spec_warnings
19
 
      @@silence_spec_warnings
20
 
    end
21
 
 
22
 
    def self.silence_spec_warnings=(v)
23
 
      @@silence_spec_warnings = v
24
 
    end
25
 
 
26
 
    def initialize(installed_index, vendor_dir=Rails::GemDependency.unpacked_path)
27
 
      @installed_source_index = installed_index
28
 
      @vendor_dir = vendor_dir
29
 
      refresh!
30
 
    end
31
 
 
32
 
    def refresh!
33
 
      # reload the installed gems
34
 
      @installed_source_index.refresh!
35
 
      vendor_gems = {}
36
 
 
37
 
      # handle vendor Rails gems - they are identified by having loaded_from set to ""
38
 
      # we add them manually to the list, so that other gems can find them via dependencies
39
 
      Gem.loaded_specs.each do |n, s|
40
 
        next unless s.loaded_from.empty?
41
 
        vendor_gems[s.full_name] = s
42
 
      end
43
 
 
44
 
      # load specifications from vendor/gems
45
 
      Dir[File.join(Rails::GemDependency.unpacked_path, '*')].each do |d|
46
 
        dir_name = File.basename(d)
47
 
        dir_version = version_for_dir(dir_name)
48
 
        spec = load_specification(d)
49
 
        if spec
50
 
          if spec.full_name != dir_name
51
 
            # mismatched directory name and gem spec - produced by 2.1.0-era unpack code
52
 
            if dir_version
53
 
              # fix the spec version - this is not optimal (spec.files may be wrong)
54
 
              # but it's better than breaking apps. Complain to remind users to get correct specs.
55
 
              # use ActiveSupport::Deprecation.warn, as the logger is not set yet
56
 
              $stderr.puts("config.gem: Unpacked gem #{dir_name} in vendor/gems has a mismatched specification file."+
57
 
                           " Run 'rake gems:refresh_specs' to fix this.") unless @@silence_spec_warnings
58
 
              spec.version = dir_version
59
 
            else
60
 
              $stderr.puts("config.gem: Unpacked gem #{dir_name} in vendor/gems is not in a versioned directory"+
61
 
                           "(should be #{spec.full_name}).") unless @@silence_spec_warnings
62
 
              # continue, assume everything is OK
63
 
            end
64
 
          end
65
 
        else
66
 
          # no spec - produced by early-2008 unpack code
67
 
          # emulate old behavior, and complain.
68
 
          $stderr.puts("config.gem: Unpacked gem #{dir_name} in vendor/gems has no specification file."+
69
 
                       " Run 'rake gems:refresh_specs' to fix this.") unless @@silence_spec_warnings
70
 
          if dir_version
71
 
            spec = Gem::Specification.new
72
 
            spec.version = dir_version
73
 
            spec.require_paths = ['lib']
74
 
            ext_path = File.join(d, 'ext')
75
 
            spec.require_paths << 'ext' if File.exist?(ext_path)
76
 
            spec.name = /^(.*)-[^-]+$/.match(dir_name)[1]
77
 
            files = ['lib']
78
 
            # set files to everything in lib/
79
 
            files += Dir[File.join(d, 'lib', '*')].map { |v| v.gsub(/^#{d}\//, '') }
80
 
            files += Dir[File.join(d, 'ext', '*')].map { |v| v.gsub(/^#{d}\//, '') } if ext_path
81
 
            spec.files = files
82
 
          else
83
 
            $stderr.puts("config.gem: Unpacked gem #{dir_name} in vendor/gems not in a versioned directory."+
84
 
                         " Giving up.") unless @@silence_spec_warnings
85
 
            next
86
 
          end
87
 
        end
88
 
        spec.loaded_from = File.join(d, '.specification')
89
 
        # finally, swap out full_gem_path
90
 
        # it would be better to use a Gem::Specification subclass, but the YAML loads an explicit class
91
 
        class << spec
92
 
          def full_gem_path
93
 
            path = File.join installation_path, full_name
94
 
            return path if File.directory? path
95
 
            File.join installation_path, original_name
96
 
          end
97
 
        end
98
 
        vendor_gems[File.basename(d)] = spec
99
 
      end
100
 
      @vendor_source_index = Gem::SourceIndex.new(vendor_gems)
101
 
    end
102
 
 
103
 
    def version_for_dir(d)
104
 
      matches = /-([^-]+)$/.match(d)
105
 
      Gem::Version.new(matches[1]) if matches
106
 
    end
107
 
 
108
 
    def load_specification(gem_dir)
109
 
      spec_file = File.join(gem_dir, '.specification')
110
 
      YAML.load_file(spec_file) if File.exist?(spec_file)
111
 
    end
112
 
 
113
 
    def find_name(*args)
114
 
      @installed_source_index.find_name(*args) + @vendor_source_index.find_name(*args)
115
 
    end
116
 
 
117
 
    def search(*args)
118
 
      # look for vendor gems, and then installed gems - later elements take priority
119
 
      @installed_source_index.search(*args) + @vendor_source_index.search(*args)
120
 
    end
121
 
 
122
 
    def each(&block)
123
 
      @vendor_source_index.each(&block)
124
 
      @installed_source_index.each(&block)
125
 
    end
126
 
 
127
 
    def add_spec(spec)
128
 
      @vendor_source_index.add_spec spec
129
 
    end
130
 
 
131
 
    def remove_spec(spec)
132
 
      @vendor_source_index.remove_spec spec
133
 
    end
134
 
 
135
 
    def size
136
 
      @vendor_source_index.size + @installed_source_index.size
137
 
    end
138
 
 
139
 
  end
140
 
end