lib/faster_require.rb in faster_require-0.6.0 vs lib/faster_require.rb in faster_require-0.7.0
- old
+ new
@@ -1,9 +1,11 @@
require 'rbconfig'
+#require 'rubygems'
+#require 'ruby-debug'
module FastRequire
- $FAST_REQUIRE_DEBUG ||= $DEBUG # can set it via $DEBUG, or by itself
+ $FAST_REQUIRE_DEBUG ||= $DEBUG # can set via $DEBUG, or on its own.
def self.setup
@@dir = File.expand_path('~/.ruby_faster_require_cache')
Dir.mkdir @@dir unless File.directory?(@@dir)
@@ -81,13 +83,13 @@
end
@@already_loaded[key] = true
}
@@already_loaded[File.expand_path(__FILE__)] = true # this file itself isn't in loaded features, yet, but very soon will be..
- # special case--I hope...
+ # a special case--I hope...
- # disallow re-requiring $0
+ # also disallow re- $0
@@require_locs[$0] = File.expand_path($0) # so when we run into it on a require, we will skip it...
@@already_loaded[File.expand_path($0)] = true
# XXXX within a very long depth to require fast_require,
# require 'a' => 'b' => 'c' => 'd' & fast_require
@@ -123,117 +125,164 @@
require 'fileutils'
FileUtils.rm_rf @@dir if File.exist? @@dir
@@require_locs.clear
setup
end
-# require 'ruby-debug'
+
+ private
+ def last_caller
+ caller[-2]
+ end
+
+ IN_PROCESS = []
+ ALL_IN_PROCESS = []
+ @@count = 0
+ public
+
def require_cached lib
lib = lib.to_s # might not be zactly 1.9 compat... to_path ??
- # p 'doing require ' + lib
- if known_loc = @@require_locs[lib]
- if @@already_loaded[known_loc]
- p 'already loaded ' + known_loc if $FAST_REQUIRE_DEBUG
- return false
- end
- @@already_loaded[known_loc] = true
- if known_loc =~ /\.#{RbConfig::CONFIG['DLEXT']}$/
- puts 'doing original_non_cached_require on .so full path ' + known_loc if $FAST_REQUIRE_DEBUG
- original_non_cached_require known_loc # not much we can do there...too bad...well at least we pass it a full path though :P
- else
- unless $LOADED_FEATURES.include? known_loc
- if known_loc =~ /rubygems.rb$/
- puts 'requiring rubygems ' + known_loc if $FAST_REQUIRE_DEBUG
- original_non_cached_require(known_loc) # normal require so rubygems doesn't freak out when it finds itself already in $LOADED_FEATURES :P
- else
- if $FAST_REQUIRE_DEBUG
- puts 'doing cached loc eval on ' + lib + '=>' + known_loc
+ ALL_IN_PROCESS << [lib, @@count += 1]
+ begin
+ p 'doing require ' + lib + ' from ' + caller[-1] if $FAST_REQUIRE_DEBUG
+ if known_loc = @@require_locs[lib]
+ if @@already_loaded[known_loc]
+ p 'already loaded ' + known_loc + ' ' + lib if $FAST_REQUIRE_DEBUG
+ return false
+ end
+ @@already_loaded[known_loc] = true
+ if known_loc =~ /\.#{RbConfig::CONFIG['DLEXT']}$/
+ puts 'doing original_non_cached_require on .so full path ' + known_loc if $FAST_REQUIRE_DEBUG
+ original_non_cached_require known_loc # not much we can do there...too bad...well at least we pass it a full path though :P
+ else
+ unless $LOADED_FEATURES.include? known_loc
+ if known_loc =~ /rubygems.rb$/
+ puts 'requiring rubygems ' + lib if $FAST_REQUIRE_DEBUG
+ original_non_cached_require(lib) # revert to normal require so rubygems doesn't freak out when it finds itself already in $LOADED_FEATURES with rubygems > 1.6 :P
+ else
+ IN_PROCESS << known_loc
+ begin
+ if $FAST_REQUIRE_DEBUG
+ puts 'doing cached loc eval on ' + lib + '=>' + known_loc + " with stack:" + IN_PROCESS.join(' ')
+ end
+ $LOADED_FEATURES << known_loc
+ # fakely add the load path, too, so that autoload for the same file/path in gems will work <sigh> [rspec2]
+ no_suffix_full_path = known_loc.gsub(/\.[^.]+$/, '')
+ no_suffix_lib = lib.gsub(/\.[^.]+$/, '')
+ libs_path = no_suffix_full_path.gsub(no_suffix_lib, '')
+ libs_path = File.expand_path(libs_path) # strip off trailing '/'
+ $: << libs_path unless $:.index(libs_path)
+ # try some more autoload conivings...so that it won't attempt to autoload if it runs into it later...
+ relative_full_path = known_loc.sub(libs_path, '')[1..-1]
+ # $LOADED_FEATURES << relative_full_path.gsub('.rb', '') # don't think you need this one
+ $LOADED_FEATURES << relative_full_path # add in with .rb, too.
+
+ # load(known_loc, false) # too slow
+ eval(File.open(known_loc, 'rb') {|f| f.read}, TOPLEVEL_BINDING, known_loc) # note the 'rb' here--this means it's reading .rb files as binary, which *typically* works...maybe unnecessary though?
+ ensure
+ raise 'unexpected' unless IN_PROCESS.pop == known_loc
+ end
+ # --if it breaks re-save the offending file in binary mode, or file an issue on the tracker...
+ return true
end
- $LOADED_FEATURES << known_loc
- # fakely add the load path, too, so that autoload for the same file will work <sigh> [rspec2]
- no_suffix_full_path = known_loc.gsub(/\.[^.]+$/, '')
- no_suffix_lib = lib.gsub(/\.[^.]+$/, '')
- libs_path = no_suffix_full_path.gsub(no_suffix_lib, '')
- libs_path = File.expand_path(libs_path) # strip off trailing '/'
- $: << libs_path unless $:.index(libs_path)
- # load(known_loc, false) # too slow
- eval(File.open(known_loc, 'rb') {|f| f.read}, TOPLEVEL_BINDING, known_loc) # note the rb here--this means it's reading .rb files as binary, which *typically* works...maybe unnecessary?
- # --if it breaks re-save the offending file in binary mode, or file an issue on the tracker...
- return true
+ else
+ puts 'ignoring already loaded [circular require?] ' + known_loc + ' ' + lib if $FAST_REQUIRE_DEBUG
end
- else
- puts 'ignoring already loaded? ' + known_loc if $FAST_REQUIRE_DEBUG
end
- end
- else
- # we don't know the location--let Ruby's original require do the heavy lifting for us here
- old = $LOADED_FEATURES.dup
- if(original_non_cached_require lib)
- # debugger might land here the first time you run a script and it doesn't have a require
- # cached yet...
- new = $LOADED_FEATURES - old
- found = new.last
-
- # incredibly, in 1.8.6, this doesn't always get set to a full path
- if RUBY_VERSION < '1.9'
- if !File.file?(found)
- # discover the full path.
- dir = $:.find{|path| File.file?(path + '/' + found)}
- return true unless dir # give up, case jruby socket.jar "mysterious"
- found = dir + '/' + found
- end
- found = File.expand_path(found);
- end
- puts 'found new loc:' + lib + '=>' + found if $FAST_REQUIRE_DEBUG
- @@require_locs[lib] = found
- @@already_loaded[found] = true
- return true
else
- puts 'already loaded, apparently' + lib if $FAST_REQUIRE_DEBUG
- # this probably was something like
- # the first pass was require 'regdeferred'
- # now it's a different require 'regdeferred.rb'
- # which fails (or vice versa)
- # so figure out why
- # calc location, expand, map back
- where_found = FastRequire.guess_discover(lib, true)
- if where_found
- puts 'inferred lib loc:' + lib + '=>' + where_found if $FAST_REQUIRE_DEBUG
- @@require_locs[lib] = where_found
- # unfortunately if it's our first pass
- # and we are in the middle of a "real" require
- # that is circular
- # then $LOADED_FEATURES or (AFAIK) nothing will have been set
- # for us to be able to assert that
- # so...I think we'll end up
- # just fudging for a bit
- # raise 'not found' unless @@already_loaded[where_found] # should have already been set...I think...
+ # we don't know the location--let Ruby's original require do the heavy lifting for us here
+ old = $LOADED_FEATURES.dup
+ if(original_non_cached_require(lib))
+ # debugger might land here the first time you run a script and it doesn't have a require
+ # cached yet...
+ new = $LOADED_FEATURES - old
+ found = new.last
+
+ # incredibly, in 1.8.x, this doesn't always get set to a full path.
+ if RUBY_VERSION < '1.9'
+ if !File.file?(found)
+ # discover the full path.
+ dir = $:.find{|path| File.file?(path + '/' + found)}
+ return true unless dir # give up, case jruby socket.jar "mysterious"
+ found = dir + '/' + found
+ end
+ found = File.expand_path(found);
+ end
+ puts 'found new loc:' + lib + '=>' + found if $FAST_REQUIRE_DEBUG
+ @@require_locs[lib] = found
+ @@already_loaded[found] = true
+ return true
else
- if $FAST_REQUIRE_DEBUG
- # happens for enumerator XXXX
- puts 'unable to infer' + lib + ' in ' if $FAST_REQUIRE_DEBUG
- @@already_loaded[found] = true # hacky
+
+ # this is expected if it's for libraries required before faster_require was [like rbconfig]
+ # raise 'actually expected' + lib if RUBY_VERSION >= '1.9.0'
+ puts 'already loaded, apparently [require returned false], trying to discover how it was redundant... ' + lib if $FAST_REQUIRE_DEBUG
+ # this probably was something like
+ # the first pass was require 'regdeferred'
+ # now it's a different require 'regdeferred.rb'
+ # which fails (or vice versa)
+ # so figure out why
+ # calc location, expand, map back
+ where_found = FastRequire.guess_discover(lib, true)
+ if where_found
+ puts 'inferred lib loc:' + lib + '=>' + where_found if $FAST_REQUIRE_DEBUG
+ @@require_locs[lib] = where_found
+ # unfortunately if it's our first pass
+ # and we are in the middle of a "real" require
+ # that is circular
+ # then $LOADED_FEATURES or (AFAIK) nothing will have been set
+ # for us to be able to assert that
+ # so...I think we'll end up
+ # just fudging for a bit
+ # raise 'not found' unless @@already_loaded[where_found] # should have already been set...I think...
+ else
+ if $FAST_REQUIRE_DEBUG
+ # happens for enumerator XXXX
+ puts 'unable to infer ' + lib + ' location' if $FAST_REQUIRE_DEBUG
+ @@already_loaded[found] = true # so hacky...
+ end
end
+ return false # XXXX test all these return values
end
- return false # XXXX test all these return values
end
+ ensure
+ raise 'huh' unless ALL_IN_PROCESS.pop[0] == lib
end
end
- def self.resetup!
- eval "module ::Kernel; alias :require :require_cached; end"
- end
end
module Kernel
if(defined?(@already_using_faster_require))
- raise 'twice not allowed...'
- # *shouldn't* ever get here...unless I'm wrong...
+ raise 'loading twice not allowed...we should never get here!'
+ end
+ @already_using_faster_require = true
+ # overwrite old require...
+ include FastRequire
+ if defined?(gem_original_require)
+ class << self
+ alias :original_remove_method :remove_method
+
+ def remove_method method # I think this actually might be needed <sigh>
+ if method.to_s == 'require'
+ #p 'not removing old require, since that\'s ours now'
+ else
+ original_remove_method method
+ end
+ end
+
+ end
+
+ # unused?
+ # def remove_method method
+ # p 'in mine2'
+ # end
+
+ # similarly overwrite this one...I guess...1.9.x...rubygems uses this as its default...I think...
+ alias :original_non_cached_require :gem_original_require
+ alias :gem_original_require :require_cached
else
- @already_using_faster_require = true
- include FastRequire
- # overwrite old require...
alias :original_non_cached_require :require
- FastRequire.resetup!
- end
+ alias :require :require_cached
+ end
-end
+end
\ No newline at end of file