summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Lerche <carllerche@mac.com>2010-02-05 21:40:48 -0800
committerCarl Lerche <carllerche@mac.com>2010-02-05 21:40:48 -0800
commit2d0524273e39d959245ababda612caa2d384c57b (patch)
tree6baeb09fad9e2ac06b59c76e16897a992e526371
parentd19c57794774e9978541a10c5e9dfa177fe6c683 (diff)
downloadbundler-2d0524273e39d959245ababda612caa2d384c57b.tar.gz
Handle rubygems executable wrappers better
-rw-r--r--lib/bundler/runtime.rb126
-rw-r--r--lib/bundler/source.rb7
-rw-r--r--spec/other/exec_spec.rb29
-rw-r--r--spec/support/builders.rb1
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