require 'pathname' require 'rubygems' Gem.source_index # ensure Rubygems is fully loaded in Ruby 1.9 module Gem class Dependency if !instance_methods.map { |m| m.to_s }.include?("requirement") def requirement version_requirements end end end end module Bundler class Specification < Gem::Specification attr_accessor :relative_loaded_from def self.from_gemspec(gemspec) spec = allocate gemspec.instance_variables.each do |ivar| spec.instance_variable_set(ivar, gemspec.instance_variable_get(ivar)) end spec end def loaded_from return super unless relative_loaded_from source.path.join(relative_loaded_from).to_s end def full_gem_path Pathname.new(loaded_from).dirname.expand_path.to_s end end module SharedHelpers attr_accessor :gem_loaded def default_gemfile gemfile = find_gemfile gemfile or raise GemfileNotFound, "Could not locate Gemfile" Pathname.new(gemfile) end def in_bundle? find_gemfile end private def find_gemfile return ENV['BUNDLE_GEMFILE'] if ENV['BUNDLE_GEMFILE'] previous = nil current = File.expand_path(Dir.pwd) until !File.directory?(current) || current == previous filename = File.join(current, 'Gemfile') return filename if File.file?(filename) current, previous = File.expand_path("..", current), current end end def clean_load_path # handle 1.9 where system gems are always on the load path if defined?(::Gem) me = File.expand_path("../../", __FILE__) $LOAD_PATH.reject! do |p| next if File.expand_path(p).include?(me) p != File.dirname(__FILE__) && Gem.path.any? { |gp| p.include?(gp) } end $LOAD_PATH.uniq! end end def reverse_rubygems_kernel_mixin # Disable rubygems' gem activation system ::Kernel.class_eval do if private_method_defined?(:gem_original_require) alias rubygems_require require alias require gem_original_require end undef gem end end def cripple_rubygems(specs) reverse_rubygems_kernel_mixin executables = specs.map { |s| s.executables }.flatten Gem.source_index # ensure RubyGems is fully loaded ::Kernel.class_eval do private def gem(*) ; end end ::Kernel.send(:define_method, :gem) do |dep, *reqs| if executables.include? File.basename(caller.first.split(':').first) return end opts = reqs.last.is_a?(Hash) ? reqs.pop : {} unless dep.respond_to?(:name) && dep.respond_to?(:requirement) dep = Gem::Dependency.new(dep, reqs) end spec = specs.find { |s| s.name == dep.name } if spec.nil? e = Gem::LoadError.new "#{dep.name} is not part of the bundle. Add it to Gemfile." e.name = dep.name e.version_requirement = dep.requirement raise e elsif dep !~ spec e = Gem::LoadError.new "can't activate #{dep}, already activated #{spec.full_name}. " \ "Make sure all dependencies are added to Gemfile." e.name = dep.name e.version_requirement = dep.requirement raise e end true end # === Following hacks are to improve on the generated bin wrappers === # Yeah, talk about a hack source_index_class = (class << Gem::SourceIndex ; self ; end) source_index_class.send(:define_method, :from_gems_in) do |*args| source_index = Gem::SourceIndex.new source_index.spec_dirs = *args source_index.add_specs(*specs) source_index end # OMG more hacks gem_class = (class << Gem ; self ; end) gem_class.send(:define_method, :bin_path) do |name, *args| exec_name, *reqs = args spec = nil if exec_name spec = specs.find { |s| s.executables.include?(exec_name) } spec or raise Gem::Exception, "can't find executable #{exec_name}" else spec = specs.find { |s| s.name == name } exec_name = spec.default_executable or raise Gem::Exception, "no default executable for #{spec.full_name}" end gem_bin = File.join(spec.full_gem_path, spec.bindir, exec_name) gem_from_path_bin = File.join(File.dirname(spec.loaded_from), spec.bindir, exec_name) File.exist?(gem_bin) ? gem_bin : gem_from_path_bin end Gem.clear_paths end extend self end end