Module: Gem::QuickLoader
- Included in:
- Gem
- Defined in:
- lib/faster_rubygems/my_gem_prelude.rb,
lib/faster_rubygems/prelude_bin_path.rb,
lib/faster_rubygems/prelude_cached_load.rb,
lib/faster_rubygems/prelude_create_cache.rb
Defined Under Namespace
Modules: PreludeRequire
Constant Summary collapse
- GemPaths =
{}
- GemVersions =
{}
- GemsActivated =
{}
- AllCaches =
if the gem dir doesn’t exist, don’t count it against us
Gem.path.select{|path| File.exist?(path)}.map{|path| cache_name = path + '/.faster_rubygems_cache' if File.exist?(cache_name) File.open(cache_name, 'rb') do |f| [path, Marshal.load(f)] end else $stderr.puts 'faster_rubygems: a cache file does not exist! reverting to full load path ' + cache_name nil end }
Class Method Summary collapse
- .fake_rubygems_as_loaded ⇒ Object
- .load_full_rubygems_library ⇒ Object
- .path_to_full_rubygems_library ⇒ Object
- .remove ⇒ Object
Instance Method Summary collapse
- #bin_path(gem_name, exec_name = nil, *version_requirements) ⇒ Object
- #calculate_all_highest_version_gems(load_them_into_the_require_path) ⇒ Object
- #const_missing(constant) ⇒ Object
- #create_cache(gems_paths) ⇒ Object
- #create_cache_for_all! ⇒ Object
-
#integers_for(gem_version) ⇒ Object
1.9.1’s gem_prelude doesn’t seem to have this for some reason…
- #method_missing(method, *args, &block) ⇒ Object
- #push_all_gems_that_might_match_and_reload_files(lib, error) ⇒ Object
- #push_gem_version_on_load_path(gem_name, *version_requirements) ⇒ Object
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, &block) ⇒ Object
348 349 350 351 352 |
# File 'lib/faster_rubygems/my_gem_prelude.rb', line 348 def method_missing(method, *args, &block) QuickLoader.load_full_rubygems_library super unless Gem.respond_to?(method) Gem.send(method, *args, &block) end |
Class Method Details
.fake_rubygems_as_loaded ⇒ Object
179 180 181 182 |
# File 'lib/faster_rubygems/my_gem_prelude.rb', line 179 def self.fake_rubygems_as_loaded path = path_to_full_rubygems_library $" << path unless $".include?(path) end |
.load_full_rubygems_library ⇒ Object
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 |
# File 'lib/faster_rubygems/my_gem_prelude.rb', line 148 def self.load_full_rubygems_library puts 'faster_rubygems: loading full rubygems',caller if $VERBOSE if $DEBUG || $VERBOSE $stderr.puts 'warning, loading full rubygems' end return if @loaded_full_rubygems_library @loaded_full_rubygems_library = true class << Gem undef_method(*Gem::GEM_PRELUDE_METHODS) 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 if path = $".detect {|path2| path2 =~ Regexp.new('/rubygems.rb$')} raise LoadError, "another rubygems is already loaded from #{path}" end require 'rubygems' begin require 'rubygems.rb.bak' # just in case rescue ::LoadError # ok end end |
.path_to_full_rubygems_library ⇒ Object
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/faster_rubygems/my_gem_prelude.rb', line 184 def self.path_to_full_rubygems_library # null rubylibprefix may mean 'you have loaded the other rubygems already somehow...' hmm prefix = (RbConfig::CONFIG["rubylibprefix"] || RbConfig::CONFIG['rubylibdir'].split('/')[0..-2].join('/')) installed_path = File.join(prefix, 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 |
.remove ⇒ Object
142 143 144 |
# File 'lib/faster_rubygems/my_gem_prelude.rb', line 142 def self.remove $stderr.puts 'warning--faster_rubygems doesnt quite yet implement remove yet, for 1.9.2--it will probably work without it though...' if $VERBOSE || $DEBUG end |
Instance Method Details
#bin_path(gem_name, exec_name = nil, *version_requirements) ⇒ Object
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 |
# File 'lib/faster_rubygems/prelude_bin_path.rb', line 4 def bin_path(gem_name, exec_name = nil, *version_requirements) unless GemPaths.has_key?(gem_name) then raise Gem::LoadError, "Could not find RubyGem #{gem_name} (>= 0)\n" end version_match = false if version_requirements.empty? version_match = true else if version_requirements.length > 1 then version_match = false else requirement, version = version_requirements[0].split requirement.strip! if loaded_version = GemVersions[gem_name] then case requirement when ">", ">=" then if (loaded_version <=> Gem.integers_for(version)) >= 0 version_match = true end when "~>" then required_version = Gem.integers_for version if loaded_version.first == required_version.first version_match = true end end end end end if version_match && exec_name full_path = GemPaths[gem_name] + '/bin/' + exec_name if File.exist? full_path return full_path end end QuickLoader.load_full_rubygems_library bin_path(gem_name, exec_name, *version_requirements) end |
#calculate_all_highest_version_gems(load_them_into_the_require_path) ⇒ Object
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 |
# File 'lib/faster_rubygems/my_gem_prelude.rb', line 284 def calculate_all_highest_version_gems load_them_into_the_require_path start = Time.now if $VERBOSE 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) # TODO lazy load these, too...why not? end end end end puts "faster_rubygems: took " + (Time.now - start).to_s + "s to scan the dirs for versions" if $VERBOSE # TODO don't require iterating over all these, since you can extrapolate them from the cache files... return unless load_them_into_the_require_path # load all lib dirs into $:... 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 # bin shouldn't be necessary... # 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'] $:[$:.find{|e|e.instance_variable_defined?(:@gem_prelude_index)}||-1,0] = require_paths end |
#const_missing(constant) ⇒ Object
337 338 339 340 341 342 343 344 345 346 |
# File 'lib/faster_rubygems/my_gem_prelude.rb', line 337 def const_missing(constant) puts 'gem_prelude: const missing', constant if $VERBOSE || $DEBUG QuickLoader.load_full_rubygems_library if Gem.const_defined?(constant) then Gem.const_get constant else super end end |
#create_cache(gems_paths) ⇒ Object
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 |
# File 'lib/faster_rubygems/prelude_create_cache.rb', line 5 def create_cache gems_paths puts 'faster_rubygems: creating caches' gems_paths.each do |path| gem_versions = {} gem_paths = {} 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 = gem_versions[gem_name] if !current_version or (current_version <=> new_version) < 0 then gem_versions[gem_name] = new_version gem_paths[gem_name] = File.join(gems_directory, gem_directory_name) end end end gem_paths_with_contents = {} # strip out directories, and the gem-d.d.d prefix gem_paths.each{|k, v| files = Dir[v + '/**/*.{rb,so,bundle}'].select{|f| !File.directory? f }.map{ |full_name| full_name.sub(v + '/', '') full_name.split('/')[-1].split('.')[0] # just a of a.b.c.rb, for now } hash_of_files = {} files.each{|small_filename| hash_of_files[small_filename] = true } gem_paths_with_contents[k] = hash_of_files } cache_path = path + '/.faster_rubygems_cache' print '.' puts cache_path if $VERBOSE $stdout.flush # accomodate for those not running as sudo... if File.writable? path File.open(cache_path, 'wb') do |f| f.write Marshal.dump(gem_paths_with_contents) end else $stderr.puts "warning, unable to write cache to:" + cache_path end end end |
#create_cache_for_all! ⇒ Object
59 60 61 62 |
# File 'lib/faster_rubygems/prelude_create_cache.rb', line 59 def create_cache_for_all! puts 'recreating all faster_rubygems caches' create_cache Gem.path end |
#integers_for(gem_version) ⇒ Object
1.9.1’s gem_prelude doesn’t seem to have this for some reason…
48 49 50 51 52 53 |
# File 'lib/faster_rubygems/prelude_bin_path.rb', line 48 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 |
#push_all_gems_that_might_match_and_reload_files(lib, error) ⇒ Object
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/faster_rubygems/prelude_cached_load.rb', line 18 def push_all_gems_that_might_match_and_reload_files lib, error sub_lib = lib.gsub("\\", '/').split('/')[-1].split('.')[0] success = false raise if AllCaches.empty? # should never be empty... AllCaches.each{|path, gem_list| for gem_name, long_file_list in gem_list if long_file_list[sub_lib] puts 'activating' + gem_name + ' ' + sub_lib.to_s if $DEBUG if gem(gem_name) puts 'gem activated ' + gem_name + ' ' + sub_lib if $VERBOSE || $DEBUG success = true end puts 'done activeating' + gem_name + ' ' + sub_lib if $DEBUG end end } success end |
#push_gem_version_on_load_path(gem_name, *version_requirements) ⇒ Object
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 |
# File 'lib/faster_rubygems/my_gem_prelude.rb', line 204 def push_gem_version_on_load_path(gem_name, *version_requirements) if version_requirements.empty? unless path = GemPaths[gem_name] then puts "Could not find RubyGem #{gem_name} (>= 0)\n" if $VERBOSE || $DEBUG raise Gem::LoadError, "Could not find RubyGem #{gem_name} (>= 0)\n" end # highest version gems *not* already active if !AllCaches.empty? # then we are using the caches, and the stuff isn't preloaded yet # copied and pasted... require_paths = [] if GemsActivated[gem_name] return false else GemsActivated[gem_name] = true end 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 # bin shouldn't be necessary... # require_paths << file if File.exist?(file = File.join(path, "bin")) require_paths << file if File.exist?(file = File.join(path, "lib")) 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'] # TODO puts $:.index{|e|e.instance_variable_defined?(:@gem_prelude_index)} # $:[$:.index{|e|e.instance_variable_defined?(:@gem_prelude_index)}||-1,0] = require_paths $:[0,0] = require_paths return true end # normal flow when not using caches--it's already on the path 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! # accomodate for gem 'xxx', '2.3.8' if !version version = requirement requirement = '=' end 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 |