diff options
author | Carl Lerche <carllerche@mac.com> | 2010-02-05 21:40:48 -0800 |
---|---|---|
committer | Carl Lerche <carllerche@mac.com> | 2010-02-05 21:40:48 -0800 |
commit | 2d0524273e39d959245ababda612caa2d384c57b (patch) | |
tree | 6baeb09fad9e2ac06b59c76e16897a992e526371 | |
parent | d19c57794774e9978541a10c5e9dfa177fe6c683 (diff) | |
download | bundler-2d0524273e39d959245ababda612caa2d384c57b.tar.gz |
Handle rubygems executable wrappers better
-rw-r--r-- | lib/bundler/runtime.rb | 126 | ||||
-rw-r--r-- | lib/bundler/source.rb | 7 | ||||
-rw-r--r-- | spec/other/exec_spec.rb | 29 | ||||
-rw-r--r-- | spec/support/builders.rb | 1 |
4 files changed, 119 insertions, 44 deletions
diff --git a/lib/bundler/runtime.rb b/lib/bundler/runtime.rb index 80fe144c6d..d5a3ccbc5b 100644 --- a/lib/bundler/runtime.rb +++ b/lib/bundler/runtime.rb @@ -3,8 +3,11 @@ require "digest/sha1" module Bundler class Runtime < Environment def setup(*groups) - specs = specs_for(*groups) # Has to happen first + clean_load_path + + specs = specs_for(*groups) + cripple_rubygems(specs) # Activate the specs @@ -119,7 +122,56 @@ module Bundler specs.map { |s| s.load_paths }.flatten end - def cripple_rubygems(specs) + def write_rb_lock + template = File.read(File.expand_path("../templates/environment.erb", __FILE__)) + erb = ERB.new(template, nil, '-') + File.open("#{root}/.bundle/environment.rb", 'w') do |f| + f.puts erb.result(binding) + end + end + + def write_yml_lock + yml = details.to_yaml + File.open("#{root}/Gemfile.lock", 'w') do |f| + f.puts yml + end + end + + def details + details = {} + details["hash"] = gemfile_fingerprint + details["sources"] = sources.map { |s| { s.class.name.split("::").last => s.options} } + + details["specs"] = specs.map do |s| + options = {"version" => s.version.to_s} + options["source"] = sources.index(s.source) if sources.include?(s.source) + { s.name => options } + end + + details["dependencies"] = @definition.dependencies.map { |d| {d.name => d.version_requirements.to_s} } + details + end + + def gemfile_fingerprint + Digest::SHA1.hexdigest(File.read("#{root}/Gemfile")) + end + + def autorequires_for_groups(*groups) + autorequires = Hash.new { |h,k| h[k] = [] } + @definition.dependencies.each do |dep| + dep.groups.each do |group| + autorequires[group].concat dep.autorequire + end + end + + if groups.empty? + autorequires + else + groups.inject({}) { |h,g| h[g] = autorequires[g]; h } + 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__) @@ -130,7 +182,9 @@ module Bundler $LOAD_PATH.unshift me $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) @@ -140,8 +194,17 @@ module Bundler undef gem end + end + + def cripple_rubygems(specs) + reverse_rubygems_kernel_mixin + + executables = specs.map { |s| s.executables }.flatten ::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?(:version_requirements) @@ -165,54 +228,33 @@ module Bundler true end - end - - def write_rb_lock - template = File.read(File.expand_path("../templates/environment.erb", __FILE__)) - erb = ERB.new(template, nil, '-') - File.open("#{root}/.bundle/environment.rb", 'w') do |f| - f.puts erb.result(binding) - end - end - - def write_yml_lock - yml = details.to_yaml - File.open("#{root}/Gemfile.lock", 'w') do |f| - f.puts yml - end - end - def details - details = {} - details["hash"] = gemfile_fingerprint - details["sources"] = sources.map { |s| { s.class.name.split("::").last => s.options} } + # === Following hacks are to improve on the generated bin wrappers === - details["specs"] = specs.map do |s| - options = {"version" => s.version.to_s} - options["source"] = sources.index(s.source) if sources.include?(s.source) - { s.name => options } + # 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.add_specs *specs + source_index end - details["dependencies"] = @definition.dependencies.map { |d| {d.name => d.version_requirements.to_s} } - details - end + # OMG more hacks + gem_class = (class << Gem ; self ; end) + gem_class.send(:define_method, :bin_path) do |name, *args| + exec_name, *reqs = args - def gemfile_fingerprint - Digest::SHA1.hexdigest(File.read("#{root}/Gemfile")) - end + spec = nil - def autorequires_for_groups(*groups) - autorequires = Hash.new { |h,k| h[k] = [] } - @definition.dependencies.each do |dep| - dep.groups.each do |group| - autorequires[group].concat dep.autorequire + 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 - end - if groups.empty? - autorequires - else - groups.inject({}) { |h,g| h[g] = autorequires[g]; h } + File.join(spec.full_gem_path, spec.bindir, exec_name) end end end diff --git a/lib/bundler/source.rb b/lib/bundler/source.rb index 70d89f8d1f..258a218961 100644 --- a/lib/bundler/source.rb +++ b/lib/bundler/source.rb @@ -30,8 +30,11 @@ module Bundler gem_path = Gem::RemoteFetcher.fetcher.download(spec, uri, destination) Bundler.ui.debug " * Installing" installer = Gem::Installer.new gem_path, - :install_dir => Gem.dir, - :ignore_dependencies => true + :install_dir => Gem.dir, + :ignore_dependencies => true, + :wrappers => true, + :env_shebang => true, + :bin_dir => "#{Gem.dir}/bin" installer.install end diff --git a/spec/other/exec_spec.rb b/spec/other/exec_spec.rb index 43e3b6f0d3..8d55221400 100644 --- a/spec/other/exec_spec.rb +++ b/spec/other/exec_spec.rb @@ -32,4 +32,33 @@ describe "bundle exec" do out.should == "1.0.0" end + + it "handles different versions in different bundles" do + build_repo2 do + build_gem "rack_two", "1.0.0" do |s| + s.executables = "rackup" + end + end + + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", "0.9.1" + G + + Dir.chdir bundled_app2 do + install_gemfile bundled_app2('Gemfile'), <<-G + source "file://#{gem_repo2}" + gem "rack_two", "1.0.0" + G + end + + bundle "exec rackup" + + out.should == "0.9.1" + + Dir.chdir bundled_app2 do + bundle "exec rackup" + out.should == "1.0.0" + end + end end
\ No newline at end of file diff --git a/spec/support/builders.rb b/spec/support/builders.rb index 8a2970e63c..ebcf741c50 100644 --- a/spec/support/builders.rb +++ b/spec/support/builders.rb @@ -110,6 +110,7 @@ module Spec build_gem "rack", "1.2" do |s| s.executables = "rackup" end + yield if block_given? end end |