From e09193328f055207c998292f1d293f75ea1e26d4 Mon Sep 17 00:00:00 2001 From: The Bundler Bot Date: Sun, 10 Sep 2017 17:58:32 +0000 Subject: Auto merge of #5803 - igorbozato:path_relative_to_pwd, r=indirect Make `install --path` relative to the pwd ### What was the end-user problem that led to this PR? > I ran the following > > bundle install --gemfile=src/main/webapp/WEB-INF/Gemfile --path ./target/bundler/ --standalone > and it generated the setup file in the following location target/bundler/bundler/setup.rb while it installed the gems in src/main/webapp/WEB-INF/target/bundler/. So it assumed that the --path was relative to the Gemfile instead of the PWD. It also created the .bundle/config in the WEB-INF folder. Closes #2048 ### Was was your diagnosis of the problem? As discussed on the issue, the path is currently being relative to the Gemfile instead of the cwd. ### What is your fix for the problem, implemented in this PR? Making the path relative to the cwd if the new feature flag `path_relative_to_cwd` is set t true. ### Why did you choose this fix out of the possible options? This work was started by @agis (https://github.com/agis/bundler/commit/1da8a7021bdd9bbe76398dddec8bc499655666dd). (cherry picked from commit 406cdc44bcafd0d89820da0c3b039d08b31db67e) --- lib/bundler/cli/install.rb | 13 ++++++---- lib/bundler/feature_flag.rb | 1 + lib/bundler/settings.rb | 15 ++++++++++++ lib/bundler/settings/validator.rb | 23 ++++++++++++++++++ man/bundle-config.ronn | 2 ++ spec/install/gems/standalone_spec.rb | 46 ++++++++++++++++++++++++------------ spec/install/path_spec.rb | 33 +++++++++++++++++++++++++- 7 files changed, 112 insertions(+), 21 deletions(-) diff --git a/lib/bundler/cli/install.rb b/lib/bundler/cli/install.rb index ea017dfc09..b40e5f0e9e 100644 --- a/lib/bundler/cli/install.rb +++ b/lib/bundler/cli/install.rb @@ -71,8 +71,7 @@ module Bundler if Bundler.use_system_gems? Bundler.ui.confirm "Use `bundle info [gemname]` to see where a bundled gem is installed." else - absolute_path = File.expand_path(Bundler.configured_bundle_path.base_path) - relative_path = absolute_path.sub(File.expand_path(".") + File::SEPARATOR, "." + File::SEPARATOR) + relative_path = Bundler.configured_bundle_path.base_path_relative_to_pwd Bundler.ui.confirm "Bundled gems are installed into `#{relative_path}`" end @@ -169,9 +168,13 @@ module Bundler def normalize_settings Bundler.settings.set_command_option :path, nil if options[:system] - Bundler.settings.set_command_option :path, "vendor/bundle" if options[:deployment] - Bundler.settings.set_command_option_if_given :path, options["path"] - Bundler.settings.set_command_option :path, "bundle" if options["standalone"] && Bundler.settings[:path].nil? + Bundler.settings.temporary(:path_relative_to_cwd => false) do + Bundler.settings.set_command_option :path, "vendor/bundle" if options[:deployment] + end + Bundler.settings.set_command_option_if_given :path, options[:path] + Bundler.settings.temporary(:path_relative_to_cwd => false) do + Bundler.settings.set_command_option :path, "bundle" if options["standalone"] && Bundler.settings[:path].nil? + end bin_option = options["binstubs"] bin_option = nil if bin_option && bin_option.empty? diff --git a/lib/bundler/feature_flag.rb b/lib/bundler/feature_flag.rb index 23e581e65e..04ad42d73d 100644 --- a/lib/bundler/feature_flag.rb +++ b/lib/bundler/feature_flag.rb @@ -44,6 +44,7 @@ module Bundler settings_flag(:list_command) { bundler_2_mode? } settings_flag(:lockfile_uses_separate_rubygems_sources) { bundler_2_mode? } settings_flag(:only_update_to_newer_versions) { bundler_2_mode? } + settings_flag(:path_relative_to_cwd) { bundler_2_mode? } settings_flag(:plugins) { @bundler_version >= Gem::Version.new("1.14") } settings_flag(:prefer_gems_rb) { bundler_2_mode? } settings_flag(:print_only_version_number) { bundler_2_mode? } diff --git a/lib/bundler/settings.rb b/lib/bundler/settings.rb index 6ba739623f..b365d08c2b 100644 --- a/lib/bundler/settings.rb +++ b/lib/bundler/settings.rb @@ -44,6 +44,7 @@ module Bundler no_install no_prune only_update_to_newer_versions + path_relative_to_cwd path.system plugins prefer_gems_rb @@ -248,6 +249,20 @@ module Bundler path end + def base_path_relative_to_pwd + base_path = Pathname.new(self.base_path) + expanded_base_path = base_path.expand_path(Bundler.root) + relative_path = expanded_base_path.relative_path_from(Pathname.pwd) + if relative_path.to_s.start_with?("..") + relative_path = base_path if base_path.absolute? + else + relative_path = Pathname.new(File.join(".", relative_path)) + end + relative_path + rescue ArgumentError + expanded_base_path + end + def validate! return unless explicit_path && system_path path = Bundler.settings.pretty_values_for(:path) diff --git a/lib/bundler/settings/validator.rb b/lib/bundler/settings/validator.rb index 9aa1627fb2..0a57ea7f03 100644 --- a/lib/bundler/settings/validator.rb +++ b/lib/bundler/settings/validator.rb @@ -74,6 +74,29 @@ module Bundler fail!(key, value, "`#{other_key}` is current set to #{other_setting.inspect}", "the `#{conflicting.join("`, `")}` groups conflict") end end + + rule %w[path], "relative paths are expanded relative to the current working directory" do |key, value, settings| + next if value.nil? + + path = Pathname.new(value) + next if !path.relative? || !Bundler.feature_flag.path_relative_to_cwd? + + path = path.expand_path + + root = begin + Bundler.root + rescue GemfileNotFound + Pathname.pwd.expand_path + end + + path = begin + path.relative_path_from(root) + rescue ArgumentError + path + end + + set(settings, key, path.to_s) + end end end end diff --git a/man/bundle-config.ronn b/man/bundle-config.ronn index 3eda468688..4d8bda61f7 100644 --- a/man/bundle-config.ronn +++ b/man/bundle-config.ronn @@ -227,6 +227,8 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html). is used, defaults to vendor/bundle. * `path.system` (`BUNDLE_PATH__SYSTEM`): Whether Bundler will install gems into the default system path (`Gem.dir`). +* `path_relative_to_cwd` (`PATH_RELATIVE_TO_CWD`) + Makes `--path` relative to the CWD instead of the `Gemfile`. * `plugins` (`BUNDLE_PLUGINS`): Enable Bundler's experimental plugin system. * `prefer_gems_rb` (`BUNDLE_PREFER_GEMS_RB`) diff --git a/spec/install/gems/standalone_spec.rb b/spec/install/gems/standalone_spec.rb index 431854e6d5..b149d9d00b 100644 --- a/spec/install/gems/standalone_spec.rb +++ b/spec/install/gems/standalone_spec.rb @@ -54,7 +54,7 @@ RSpec.shared_examples "bundle install --standalone" do source "file://#{gem_repo1}" gem "rails" G - bundle! :install, forgotten_command_line_options(:path => "bundle").merge(:standalone => true) + bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true) end let(:expected_gems) do @@ -69,14 +69,15 @@ RSpec.shared_examples "bundle install --standalone" do describe "with gems with native extension" do before do - install_gemfile <<-G, forgotten_command_line_options(:path => "bundle").merge(:standalone => true) + install_gemfile <<-G, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true) source "file://#{gem_repo1}" gem "very_simple_binary" G end it "generates a bundle/bundler/setup.rb with the proper paths", :rubygems => "2.4" do - extension_line = File.read(bundled_app("bundle/bundler/setup.rb")).each_line.find {|line| line.include? "/extensions/" }.strip + expected_path = bundled_app("bundle/bundler/setup.rb") + extension_line = File.read(expected_path).each_line.find {|line| line.include? "/extensions/" }.strip expect(extension_line).to start_with '$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/' expect(extension_line).to end_with '/very_simple_binary-1.0"' end @@ -101,7 +102,7 @@ RSpec.shared_examples "bundle install --standalone" do end G end - install_gemfile <<-G, forgotten_command_line_options(:path => "bundle").merge(:standalone => true) + install_gemfile <<-G, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true) gem "bar", :git => "#{lib_path("bar-1.0")}" G end @@ -121,7 +122,7 @@ RSpec.shared_examples "bundle install --standalone" do gem "rails" gem "devise", :git => "#{lib_path("devise-1.0")}" G - bundle! :install, forgotten_command_line_options(:path => "bundle").merge(:standalone => true) + bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true) end let(:expected_gems) do @@ -148,7 +149,7 @@ RSpec.shared_examples "bundle install --standalone" do gem "rack-test" end G - bundle! :install, forgotten_command_line_options(:path => "bundle").merge(:standalone => true) + bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true) end let(:expected_gems) do @@ -161,7 +162,7 @@ RSpec.shared_examples "bundle install --standalone" do include_examples "common functionality" it "allows creating a standalone file with limited groups" do - bundle! "install", forgotten_command_line_options(:path => "bundle").merge(:standalone => "default") + bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => "default") Dir.chdir(bundled_app) do load_error_ruby <<-RUBY, "spec", :no_lib => true @@ -179,7 +180,7 @@ RSpec.shared_examples "bundle install --standalone" do end it "allows --without to limit the groups used in a standalone" do - bundle! :install, forgotten_command_line_options(:path => "bundle", :without => "test").merge(:standalone => true) + bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle"), :without => "test").merge(:standalone => true) Dir.chdir(bundled_app) do load_error_ruby <<-RUBY, "spec", :no_lib => true @@ -196,7 +197,7 @@ RSpec.shared_examples "bundle install --standalone" do expect(last_command.stderr).to eq("ZOMG LOAD ERROR") end - it "allows --path to change the location of the standalone bundle" do + it "allows --path to change the location of the standalone bundle", :bundler => "< 2" do bundle! "install", forgotten_command_line_options(:path => "path/to/bundle").merge(:standalone => true) Dir.chdir(bundled_app) do @@ -212,9 +213,26 @@ RSpec.shared_examples "bundle install --standalone" do expect(last_command.stdout).to eq("2.3.2") end + it "allows --path to change the location of the standalone bundle", :bundler => "2" do + bundle! "install", forgotten_command_line_options(:path => "path/to/bundle").merge(:standalone => true) + path = File.expand_path("path/to/bundle") + + Dir.chdir(bundled_app) do + ruby <<-RUBY, :no_lib => true + $:.unshift File.expand_path(#{path.dump}) + require "bundler/setup" + + require "actionpack" + puts ACTIONPACK + RUBY + end + + expect(last_command.stdout).to eq("2.3.2") + end + it "allows remembered --without to limit the groups used in a standalone" do bundle! :install, forgotten_command_line_options(:without => "test") - bundle! :install, forgotten_command_line_options(:path => "bundle").merge(:standalone => true) + bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true) Dir.chdir(bundled_app) do load_error_ruby <<-RUBY, "spec", :no_lib => true @@ -241,7 +259,7 @@ RSpec.shared_examples "bundle install --standalone" do source "#{source_uri}" gem "rails" G - bundle! :install, forgotten_command_line_options(:path => "bundle").merge(:standalone => true, :artifice => "endpoint") + bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true, :artifice => "endpoint") end let(:expected_gems) do @@ -261,7 +279,7 @@ RSpec.shared_examples "bundle install --standalone" do source "file://#{gem_repo1}" gem "rails" G - bundle! :install, forgotten_command_line_options(:path => "bundle").merge(:standalone => true, :binstubs => true) + bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true, :binstubs => true) end let(:expected_gems) do @@ -312,9 +330,7 @@ end RSpec.describe "bundle install --standalone run in a subdirectory" do before do - subdir = bundled_app("bob") - FileUtils.mkdir_p(subdir) - Dir.chdir(subdir) + Dir.chdir(bundled_app("bob").tap(&:mkpath)) end include_examples("bundle install --standalone") diff --git a/spec/install/path_spec.rb b/spec/install/path_spec.rb index 59d151e5bf..5f3fedb862 100644 --- a/spec/install/path_spec.rb +++ b/spec/install/path_spec.rb @@ -23,7 +23,7 @@ RSpec.describe "bundle install" do dir.mkpath Dir.chdir(dir) do - bundle! :install, forgotten_command_line_options(:path => "vendor/bundle") + bundle! :install, forgotten_command_line_options(:path => dir.join("vendor/bundle")) expect(out).to include("installed into `./vendor/bundle`") end @@ -49,6 +49,37 @@ RSpec.describe "bundle install" do expect(vendored_gems("gems/rack-1.0.0")).to be_directory expect(the_bundle).to include_gems "rack 1.0.0" end + + context "with path_relative_to_cwd set to true" do + before { bundle! "config path_relative_to_cwd true" } + + it "installs the bundle relatively to current working directory", :bundler => "< 2" do + Dir.chdir(bundled_app.parent) do + bundle! "install --gemfile='#{bundled_app}/Gemfile' --path vendor/bundle" + expect(out).to include("installed into `./vendor/bundle`") + expect(bundled_app("../vendor/bundle")).to be_directory + end + expect(the_bundle).to include_gems "rack 1.0.0" + end + + it "installs the standalone bundle relative to the cwd" do + Dir.chdir(bundled_app.parent) do + bundle! :install, :gemfile => bundled_app("Gemfile"), :standalone => true + expect(out).to include("installed into `./bundled_app/bundle`") + expect(bundled_app("bundle")).to be_directory + expect(bundled_app("bundle/ruby")).to be_directory + end + + bundle! "config unset path" + + Dir.chdir(bundled_app("subdir").tap(&:mkpath)) do + bundle! :install, :gemfile => bundled_app("Gemfile"), :standalone => true + expect(out).to include("installed into `../bundle`") + expect(bundled_app("bundle")).to be_directory + expect(bundled_app("bundle/ruby")).to be_directory + end + end + end end describe "when BUNDLE_PATH or the global path config is set" do -- cgit v1.2.1