diff options
author | Homu <homu@barosl.com> | 2016-02-25 14:12:22 +0900 |
---|---|---|
committer | Homu <homu@barosl.com> | 2016-02-25 14:12:22 +0900 |
commit | 5eab4722511d53bd53d1e9a55cb7a4535c0365ee (patch) | |
tree | 3ef95f0d34bebb563ecc9dea569022d4b35359d7 /spec | |
parent | 43b31afde9628c211f5ebd82bb46cab5982a80c4 (diff) | |
parent | 45136c90c3be96107c6a350cff22072cf318bba9 (diff) | |
download | bundler-5eab4722511d53bd53d1e9a55cb7a4535c0365ee.tar.gz |
Auto merge of #4271 - bundler:seg-load-exec, r=indirect
[Exec] Load instead of exec-ing
Proof-of-concept to avoid `exec` where possible, instead just using `load` when we'd be launching the same interpreter anyways. About a .2 second gain in my limited testing. Over a second gain in jruby in my testing, somehow.
Not near ready for merging, but pretty cool for an hour of hacking.
- [x] Tests
- [ ] Centralize error handling
- [ ] Raise exceptions instead of exiting
Diffstat (limited to 'spec')
-rw-r--r-- | spec/commands/exec_spec.rb | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/spec/commands/exec_spec.rb b/spec/commands/exec_spec.rb index 16e853bb1d..be2f8aa2a5 100644 --- a/spec/commands/exec_spec.rb +++ b/spec/commands/exec_spec.rb @@ -363,4 +363,92 @@ describe "bundle exec" do expect(out).to match("true") end end + + context "`load`ing a ruby file instead of `exec`ing" do + let(:path) { bundled_app("ruby_executable") } + let(:shebang) { "#!/usr/bin/env ruby" } + let(:executable) { <<-RUBY.gsub(/^ */, "").strip } + #{shebang} + + require "rack" + puts "EXEC: \#{caller.grep(/load/).empty? ? 'exec' : 'load'}" + puts "ARGS: \#{$0} \#{ARGV.join(' ')}" + puts "RACK: \#{RACK}" + RUBY + + before do + path.open("w") {|f| f << executable } + path.chmod(0755) + + install_gemfile <<-G + gem "rack" + G + end + + let(:exec) { "EXEC: load" } + let(:args) { "ARGS: #{path} arg1 arg2" } + let(:rack) { "RACK: 1.0.0" } + let(:exit_code) { 0 } + let(:expected) { [exec, args, rack].join("\n") } + let(:expected_err) { "" } + + subject { bundle "exec #{path} arg1 arg2", :expect_err => true } + + shared_examples_for "it runs" do + it "like a normally executed executable like a normally executed executable" do + subject + expect(exitstatus).to eq(exit_code) if exitstatus + expect(err).to eq(expected_err) + expect(out).to eq(expected) + end + end + + it_behaves_like "it runs" + + context "the executable exits explicitly" do + let(:executable) { super() << "\nexit #{exit_code}\nputs 'POST_EXIT'\n" } + + context "with exit 0" do + it_behaves_like "it runs" + end + + context "with exit 99" do + let(:exit_code) { 99 } + it_behaves_like "it runs" + end + end + + context "the executable raises" do + let(:executable) { super() << "\nraise 'ERROR'" } + let(:exit_code) { 1 } + let(:expected) { super() << "\nbundler: failed to load command: #{path} (#{path})" } + let(:expected_err) do + "RuntimeError: ERROR\n #{path}:7" + + (Bundler.current_ruby.ruby_18? ? "" : ":in `<top (required)>'") + end + it_behaves_like "it runs" + end + + context "when the file uses the current ruby shebang" do + let(:shebang) { "#!#{Gem.ruby}" } + it_behaves_like "it runs" + end + + context "when Bundler.setup fails" do + before do + gemfile <<-G + gem 'rack', '2' + G + ENV["BUNDLER_FORCE_TTY"] = "true" + end + + let(:exit_code) { Bundler::GemNotFound.new.status_code } + let(:expected) { <<-EOS.strip } +\e[31mCould not find gem 'rack (= 2)' in any of the gem sources listed in your Gemfile or available on this machine.\e[0m +\e[33mRun `bundle install` to install missing gems.\e[0m + EOS + + it_behaves_like "it runs" + end + end end |