1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
|
# depends on: array.rb dir.rb env.rb file.rb hash.rb module.rb regexp.rb
# vim: filetype=ruby
# NOTICE: Ruby is during initialization here.
# * Encoding.default_external does not reflects -E.
# * Should not expect Encoding.default_internal.
# * Locale encoding is available.
if defined?(Gem) then
# :stopdoc:
module Kernel
def gem(gem_name, *version_requirements)
Gem.push_gem_version_on_load_path(gem_name, *version_requirements)
end
private :gem
end
module Gem
ConfigMap = {
:EXEEXT => RbConfig::CONFIG["EXEEXT"],
:RUBY_SO_NAME => RbConfig::CONFIG["RUBY_SO_NAME"],
:arch => RbConfig::CONFIG["arch"],
:bindir => RbConfig::CONFIG["bindir"],
:libdir => RbConfig::CONFIG["libdir"],
:ruby_install_name => RbConfig::CONFIG["ruby_install_name"],
:ruby_version => RbConfig::CONFIG["ruby_version"],
:rubylibprefix => RbConfig::CONFIG["rubylibprefix"],
:sitedir => RbConfig::CONFIG["sitedir"],
:sitelibdir => RbConfig::CONFIG["sitelibdir"],
}
def self.dir
@gem_home ||= nil
set_home(ENV['GEM_HOME'] || default_dir) unless @gem_home
@gem_home
end
def self.path
@gem_path ||= nil
unless @gem_path
paths = [ENV['GEM_PATH'] || default_path]
paths << APPLE_GEM_HOME if defined? APPLE_GEM_HOME
set_paths(paths.compact.join(File::PATH_SEPARATOR))
end
@gem_path
end
def self.post_install(&hook)
@post_install_hooks << hook
end
def self.post_uninstall(&hook)
@post_uninstall_hooks << hook
end
def self.pre_install(&hook)
@pre_install_hooks << hook
end
def self.pre_uninstall(&hook)
@pre_uninstall_hooks << hook
end
def self.set_home(home)
home = home.dup.force_encoding(Encoding.find('filesystem'))
home.gsub!(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
@gem_home = home
end
def self.set_paths(gpaths)
if gpaths
@gem_path = gpaths.split(File::PATH_SEPARATOR)
if File::ALT_SEPARATOR then
@gem_path.map! do |path|
path.gsub File::ALT_SEPARATOR, File::SEPARATOR
end
end
@gem_path << Gem.dir
else
# TODO: should this be Gem.default_path instead?
@gem_path = [Gem.dir]
end
@gem_path.uniq!
@gem_path.map!{|x|x.force_encoding(Encoding.find('filesystem'))}
end
def self.user_home
@user_home ||= File.expand_path("~").force_encoding(Encoding.find('filesystem'))
rescue
if File::ALT_SEPARATOR then
"C:/"
else
"/"
end
end
# begin rubygems/defaults
# NOTE: this require will be replaced with in-place eval before compilation.
require 'lib/rubygems/defaults.rb'
# end rubygems/defaults
##
# Methods before this line will be removed when QuickLoader is replaced
# with the real RubyGems
GEM_PRELUDE_METHODS = Gem.methods(false)
begin
verbose, debug = $VERBOSE, $DEBUG
$VERBOSE = $DEBUG = nil
begin
require 'rubygems/defaults/operating_system'
rescue ::LoadError
end
if defined?(RUBY_ENGINE) then
begin
require "rubygems/defaults/#{RUBY_ENGINE}"
rescue ::LoadError
end
end
ensure
$VERBOSE, $DEBUG = verbose, debug
end
module QuickLoader
@loaded_full_rubygems_library = false
def self.load_full_rubygems_library
return if @loaded_full_rubygems_library
@loaded_full_rubygems_library = true
class << Gem
Gem::GEM_PRELUDE_METHODS.each do |method_name|
undef_method method_name
end
undef_method :const_missing
undef_method :method_missing
end
Kernel.module_eval do
undef_method :gem if method_defined? :gem
end
$".delete path_to_full_rubygems_library
$".each do |path|
if /#{Regexp.escape File::SEPARATOR}rubygems\.rb\z/ =~ path
raise LoadError, "another rubygems is already loaded from #{path}"
end
end
require 'rubygems'
end
def self.fake_rubygems_as_loaded
path = path_to_full_rubygems_library
$" << path unless $".include?(path)
end
def self.path_to_full_rubygems_library
installed_path = File.join(Gem::ConfigMap[:rubylibprefix], Gem::ConfigMap[:ruby_version])
if $:.include?(installed_path)
return File.join(installed_path, 'rubygems.rb')
else # e.g., on test-all
$:.each do |dir|
if File.exist?( path = File.join(dir, 'rubygems.rb') )
return path
end
end
raise LoadError, 'rubygems.rb'
end
end
GemPaths = {}
GemVersions = {}
def push_gem_version_on_load_path(gem_name, *version_requirements)
if version_requirements.empty?
unless GemPaths.has_key?(gem_name) then
raise Gem::LoadError, "Could not find RubyGem #{gem_name} (>= 0)\n"
end
# highest version gems already active
return false
else
if version_requirements.length > 1 then
QuickLoader.load_full_rubygems_library
return gem(gem_name, *version_requirements)
end
requirement, version = version_requirements[0].split
requirement.strip!
if loaded_version = GemVersions[gem_name] then
case requirement
when ">", ">=" then
return false if
(loaded_version <=> Gem.integers_for(version)) >= 0
when "~>" then
required_version = Gem.integers_for version
return false if loaded_version.first == required_version.first
end
end
QuickLoader.load_full_rubygems_library
gem gem_name, *version_requirements
end
end
def integers_for(gem_version)
numbers = gem_version.split(".").collect {|n| n.to_i}
numbers.pop while numbers.last == 0
numbers << 0 if numbers.empty?
numbers
end
def push_all_highest_version_gems_on_load_path
Gem.path.each do |path|
gems_directory = File.join(path, "gems")
if File.exist?(gems_directory) then
Dir.entries(gems_directory).each do |gem_directory_name|
next if gem_directory_name == "." || gem_directory_name == ".."
next unless gem_name = gem_directory_name[/(.*)-(.*)/, 1]
new_version = integers_for($2)
current_version = GemVersions[gem_name]
if !current_version or (current_version <=> new_version) < 0 then
GemVersions[gem_name] = new_version
GemPaths[gem_name] = File.join(gems_directory, gem_directory_name)
end
end
end
end
require_paths = []
GemPaths.each_value do |path|
if File.exist?(file = File.join(path, ".require_paths")) then
paths = File.read(file).split.map do |require_path|
File.join path, require_path
end
require_paths.concat paths
else
require_paths << file if File.exist?(file = File.join(path, "bin"))
require_paths << file if File.exist?(file = File.join(path, "lib"))
end
end
# "tag" the first require_path inserted into the $LOAD_PATH to enable
# indexing correctly with rubygems proper when it inserts an explicitly
# gem version
unless require_paths.empty? then
require_paths.first.instance_variable_set(:@gem_prelude_index, true)
end
# gem directories must come after -I and ENV['RUBYLIB']
$:[$:.index{|e|e.instance_variable_defined?(:@gem_prelude_index)}||-1,0] = require_paths
end
def const_missing(constant)
QuickLoader.load_full_rubygems_library
if Gem.const_defined?(constant) then
Gem.const_get constant
else
super
end
end
def method_missing(method, *args, &block)
QuickLoader.load_full_rubygems_library
super unless Gem.respond_to?(method)
Gem.send(method, *args, &block)
end
end
extend QuickLoader
end
begin
Gem.push_all_highest_version_gems_on_load_path
Gem::QuickLoader.fake_rubygems_as_loaded
rescue Exception => e
puts "Error loading gem paths on load path in gem_prelude"
puts e
puts e.backtrace.join("\n")
end
end
|