From 5efd03e2aa01541c41a3965676b5407ed67445d7 Mon Sep 17 00:00:00 2001 From: Vinicius Stock Date: Thu, 12 Dec 2024 12:32:46 -0500 Subject: [PATCH] Recover from uninstalled gems in launcher mode --- lib/ruby_lsp/setup_bundler.rb | 9 ++++++--- test/setup_bundler_test.rb | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/lib/ruby_lsp/setup_bundler.rb b/lib/ruby_lsp/setup_bundler.rb index 45c4b59ce..9e7684290 100644 --- a/lib/ruby_lsp/setup_bundler.rb +++ b/lib/ruby_lsp/setup_bundler.rb @@ -235,12 +235,12 @@ def run_bundle_install(bundle_gemfile = @gemfile) env end - sig { params(env: T::Hash[String, String]).returns(T::Hash[String, String]) } - def run_bundle_install_directly(env) + sig { params(env: T::Hash[String, String], force_install: T::Boolean).returns(T::Hash[String, String]) } + def run_bundle_install_directly(env, force_install: false) RubyVM::YJIT.enable if defined?(RubyVM::YJIT.enable) T.unsafe(ENV).merge!(env) - unless should_bundle_update? + unless should_bundle_update? && !force_install Bundler::CLI::Install.new({}).run correct_relative_remote_paths if @custom_lockfile.exist? return env @@ -255,6 +255,9 @@ def run_bundle_install_directly(env) correct_relative_remote_paths if @custom_lockfile.exist? @last_updated_path.write(Time.now.iso8601) env + rescue Bundler::GemNotFound, Bundler::GitError + # If a gem is not installed, skip the upgrade and try to install it with a single retry + @retry ? env : run_bundle_install_directly(env, force_install: true) end sig { params(env: T::Hash[String, String]).returns(T::Hash[String, String]) } diff --git a/test/setup_bundler_test.rb b/test/setup_bundler_test.rb index b7cb8980f..004552cf1 100644 --- a/test/setup_bundler_test.rb +++ b/test/setup_bundler_test.rb @@ -823,6 +823,41 @@ def test_is_resilient_to_gemfile_changes_in_the_middle_of_setup end end + def test_update_does_not_fail_if_gems_are_uninstalled + Dir.mktmpdir do |dir| + Dir.chdir(dir) do + File.write(File.join(dir, "Gemfile"), <<~GEMFILE) + source "https://rubygems.org" + gem "rdoc" + GEMFILE + + capture_subprocess_io do + Bundler.with_unbundled_env do + system("bundle install") + run_script(dir) + + mock_update = mock("update") + mock_update.expects(:run).raises(Bundler::GemNotFound.new("rdoc")) + require "bundler/cli/update" + Bundler::CLI::Update.expects(:new).with( + { conservative: true }, + ["ruby-lsp", "debug", "prism"], + ).returns(mock_update) + + mock_install = mock("install") + mock_install.expects(:run) + require "bundler/cli/install" + Bundler::CLI::Install.expects(:new).with({}).returns(mock_install) + + RubyLsp::SetupBundler.new(dir, launcher: true).setup! + end + end + + refute_path_exists(File.join(".ruby-lsp", "install_error")) + end + end + end + private def with_default_external_encoding(encoding, &block)