From 53a6e071ea4a22d8b1c3d10de05a16e6c3e205b0 Mon Sep 17 00:00:00 2001 From: Vinicius Stock Date: Mon, 17 Jul 2023 10:44:01 -0600 Subject: [PATCH] Make sure to run bundle install even when not altering the custom bundle --- lib/ruby_lsp/setup_bundler.rb | 54 +++++++++++++++++++++++------------ test/setup_bundler_test.rb | 33 +++++++++++++++++---- 2 files changed, 64 insertions(+), 23 deletions(-) diff --git a/lib/ruby_lsp/setup_bundler.rb b/lib/ruby_lsp/setup_bundler.rb index e7f81c13b5..1a74361fa6 100644 --- a/lib/ruby_lsp/setup_bundler.rb +++ b/lib/ruby_lsp/setup_bundler.rb @@ -9,9 +9,41 @@ # the Ruby LSP without including the gem in their application's Gemfile while at the same time giving us access to the # exact locked versions of dependencies. +run_bundle_install = lambda do |dependencies, bundle_gemfile = nil| + # If the user has a custom bundle path configured, we need to ensure that we will use the absolute and not relative + # version of it when running bundle install. This is necessary to avoid installing the gems under the `.ruby-lsp` + # folder, which is not the user's intention. For example, if path is configured as `vendor`, we want to install it in + # the top level `vendor` and not `.ruby-lsp/vendor` + path = Bundler.settings["path"] + + command = +"" + # Use the absolute `BUNDLE_PATH` to prevent accidentally creating unwanted folders under `.ruby-lsp` + command << "BUNDLE_PATH=#{File.expand_path(path, Dir.pwd)} " if path + command << "BUNDLE_GEMFILE=#{bundle_gemfile} " if bundle_gemfile + + if dependencies["ruby-lsp"] && dependencies["debug"] + # Install gems using the custom bundle + command << "bundle install " + else + # If ruby-lsp or debug are not in the Gemfile, try to update them to the latest version + command << "bundle update " + command << "ruby-lsp " unless dependencies["ruby-lsp"] + command << "debug " unless dependencies["debug"] + end + + # Redirect stdout to stderr to prevent going into an infinite loop. The extension might confuse stdout output with + # responses + command << "1>&2" + + # Add bundle update + warn("Ruby LSP> Running bundle install for the custom bundle. This may take a while...") + system(command) +end + # Do not setup a custom bundle if we're working on the Ruby LSP, since it's already included by default -if Pathname.new(Dir.pwd).basename == "ruby-lsp" +if Pathname.new(Dir.pwd).basename.to_s == "ruby-lsp" warn("Ruby LSP> Skipping custom bundle setup since we're working on the Ruby LSP itself") + run_bundle_install.call({}) return end @@ -30,6 +62,7 @@ # Do not setup a custom bundle if both `ruby-lsp` and `debug` are already in the Gemfile if dependencies["ruby-lsp"] && dependencies["debug"] warn("Ruby LSP> Skipping custom bundle setup since both `ruby-lsp` and `debug` are already in the Gemfile") + run_bundle_install.call(dependencies) return end @@ -62,25 +95,10 @@ # updated, then we're ready to boot the server if File.exist?(".ruby-lsp/Gemfile.lock") && File.stat(".ruby-lsp/Gemfile.lock").mtime > File.stat("Gemfile.lock").mtime warn("Ruby LSP> Skipping custom bundle setup since .ruby-lsp/Gemfile.lock already exists and is up to date") + run_bundle_install.call(dependencies, ".ruby-lsp/Gemfile") return end FileUtils.cp("Gemfile.lock", ".ruby-lsp/Gemfile.lock") -# If the user has a custom bundle path configured, we need to ensure that we will use the absolute and not relative -# version of it when running bundle install. This is necessary to avoid installing the gems under the `.ruby-lsp` -# folder, which is not the user's intention. For example, if path is configured as `vendor`, we want to install it in -# the top level `vendor` and not `.ruby-lsp/vendor` -path = Bundler.settings["path"] - -command = +"" -# Use the absolute `BUNDLE_PATH` to prevent accidentally creating unwanted folders under `.ruby-lsp` -command << "BUNDLE_PATH=#{File.expand_path(path, Dir.pwd)} " if path -# Install gems using the custom bundle -command << "BUNDLE_GEMFILE=.ruby-lsp/Gemfile bundle install " -# Redirect stdout to stderr to prevent going into an infinite loop. The extension might confuse stdout output with -# responses -command << "1>&2" - -warn("Ruby LSP> Running bundle install for the custom bundle. This may take a while...") -system(command) +run_bundle_install.call(dependencies, ".ruby-lsp/Gemfile") diff --git a/test/setup_bundler_test.rb b/test/setup_bundler_test.rb index 20e2b971d6..21d3afd4e8 100644 --- a/test/setup_bundler_test.rb +++ b/test/setup_bundler_test.rb @@ -5,18 +5,22 @@ class SetupBundlerTest < Minitest::Test def test_does_nothing_when_running_in_the_ruby_lsp + Object.any_instance.expects(:system).with(bundle_install_command) run_script refute_path_exists(".ruby-lsp") end def test_does_nothing_if_both_ruby_lsp_and_debug_are_in_the_bundle + Pathname.any_instance.expects(:basename).returns("fake_project") + Object.any_instance.expects(:system).with(bundle_install_command(nil, false)) Bundler::LockfileParser.any_instance.expects(:dependencies).returns({ "ruby-lsp" => true, "debug" => true }) run_script refute_path_exists(".ruby-lsp") end def test_creates_custom_bundle - Object.any_instance.expects(:system).with(bundle_install_command) + Pathname.any_instance.expects(:basename).returns("fake_project") + Object.any_instance.expects(:system).with(bundle_install_command(".ruby-lsp/Gemfile")) Bundler::LockfileParser.any_instance.expects(:dependencies).returns({}) run_script @@ -30,7 +34,8 @@ def test_creates_custom_bundle end def test_copies_gemfile_lock_when_modified - Object.any_instance.expects(:system).with(bundle_install_command) + Pathname.any_instance.expects(:basename).returns("fake_project") + Object.any_instance.expects(:system).with(bundle_install_command(".ruby-lsp/Gemfile")) Bundler::LockfileParser.any_instance.expects(:dependencies).returns({}) FileUtils.mkdir(".ruby-lsp") FileUtils.touch(".ruby-lsp/Gemfile.lock") @@ -45,9 +50,22 @@ def test_copies_gemfile_lock_when_modified FileUtils.rm_r(".ruby-lsp") end + def test_does_not_copy_gemfile_lock_when_not_modified + Pathname.any_instance.expects(:basename).returns("fake_project") + Object.any_instance.expects(:system).with(bundle_install_command(".ruby-lsp/Gemfile")) + Bundler::LockfileParser.any_instance.expects(:dependencies).returns({}) + FileUtils.mkdir(".ruby-lsp") + FileUtils.cp("Gemfile.lock", ".ruby-lsp/Gemfile.lock") + + run_script + ensure + FileUtils.rm_r(".ruby-lsp") + end + def test_uses_absolute_bundle_path_for_bundle_install + Pathname.any_instance.expects(:basename).returns("fake_project") Bundler.settings.set_global("path", "vendor/bundle") - Object.any_instance.expects(:system).with(bundle_install_command) + Object.any_instance.expects(:system).with(bundle_install_command(".ruby-lsp/Gemfile")) Bundler::LockfileParser.any_instance.expects(:dependencies).returns({}) run_script ensure @@ -67,12 +85,17 @@ def run_script $LOADED_FEATURES.delete(path) end - def bundle_install_command + def bundle_install_command(bundle_gemfile = nil, update = true) path = Bundler.settings["path"] command = +"" command << "BUNDLE_PATH=#{File.expand_path(path, Dir.pwd)} " if path - command << "BUNDLE_GEMFILE=.ruby-lsp/Gemfile bundle install " + command << "BUNDLE_GEMFILE=#{bundle_gemfile} " if bundle_gemfile + command << if update + "bundle update ruby-lsp debug " + else + "bundle install " + end command << "1>&2" end end