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
13 attr_reader
:installed_source_index
14 attr_reader
:vendor_source_index
16 @
@silence_spec_warnings = false
18 def self.silence_spec_warnings
19 @
@silence_spec_warnings
22 def self.silence_spec_warnings
=(v
)
23 @
@silence_spec_warnings = v
26 def initialize(installed_index
, vendor_dir
=Rails
::GemDependency.unpacked_path
)
27 @installed_source_index = installed_index
28 @vendor_dir = vendor_dir
33 # reload the installed gems
34 @installed_source_index.refresh
!
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
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
)
50 if spec
.full_name
!= dir_name
51 # mismatched directory name and gem spec - produced by 2.1.0-era unpack code
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
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
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
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]
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
83 $stderr.puts("config.gem: Unpacked gem #{dir_name} in vendor/gems not in a versioned directory."+
84 " Giving up.") unless @
@silence_spec_warnings
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
93 path
= File
.join installation_path
, full_name
94 return path
if File
.directory
? path
95 File
.join installation_path
, original_name
98 vendor_gems
[File
.basename(d
)] = spec
100 @vendor_source_index = Gem
::SourceIndex.new(vendor_gems
)
103 def version_for_dir(d
)
104 matches
= /-([^-]+)$/.match(d
)
105 Gem
::Version.new(matches
[1]) if matches
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
)
114 @installed_source_index.find_name(*args
) + @vendor_source_index.find_name(*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
)
123 @vendor_source_index.each(&block
)
124 @installed_source_index.each(&block
)
128 @vendor_source_index.add_spec spec
131 def remove_spec(spec
)
132 @vendor_source_index.remove_spec spec
136 @vendor_source_index.size
+ @installed_source_index.size