module RorVsWild class Locator attr_reader :current_path def initialize(current_path = ENV["PWD"]) @current_path = current_path end def find_most_relevant_file_and_line(locations) location = find_most_relevant_location(locations) [relative_path(location.path), location.lineno] end def find_most_relevant_location(locations) locations.find { |l| relevant_path?(l.path) } || locations.find { |l| !irrelevant_path?(l.path) } || locations.first end def find_most_relevant_file_and_line_from_exception(exception) # Exception#backtrace_locations is faster but exists since 2.1.0. # Sometime Exception#backtrace_locations returns nil for an unknow reason. So we fallback to the old way. if exception.respond_to?(:backtrace_locations) && locations = exception.backtrace_locations find_most_relevant_file_and_line(locations) elsif (backtrace = exception.backtrace) && backtrace.size > 0 find_most_relevant_file_and_line_from_array_of_strings(backtrace) else ["No backtrace".freeze, 1] end end def find_most_relevant_file_and_line_from_array_of_strings(stack) location = stack.find { |str| relevant_path?(str) } location ||= stack.find { |str| !irrelevant_path?(str) } relative_path(location || stack.first).split(":".freeze) end def relative_path(path) path.start_with?(current_path) ? path.sub(current_path, "".freeze) : path end def relevant_path?(path) path.start_with?(current_path) && !irrelevant_path?(path) end def irrelevant_path?(path) path.start_with?(*irrelevant_paths) end def irrelevant_paths @irrelevant_paths ||= initialize_irrelevant_paths end private def initialize_irrelevant_paths array = ["RUBYLIB", "GEM_HOME", "GEM_PATH", "BUNDLER_ORIG_GEM_PATH"].flat_map do |name| ENV[name].split(":".freeze) if ENV[name] end array += [heroku_ruby_lib_path] if File.exists?(heroku_ruby_lib_path) array += Gem.path array.compact.uniq end def heroku_ruby_lib_path "/app/vendor/ruby-#{RUBY_VERSION}/lib" end end end