Skip to content

Commit

Permalink
Recover from uninstalled gems in launcher mode
Browse files Browse the repository at this point in the history
  • Loading branch information
vinistock committed Dec 16, 2024
1 parent 32d8431 commit da83fae
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 3 deletions.
9 changes: 6 additions & 3 deletions lib/ruby_lsp/setup_bundler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -241,16 +241,16 @@ 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)

# The ENV can only be merged after checking if an update is required because we depend on the original value of
# ENV["BUNDLE_GEMFILE"], which gets overridden after the merge
should_update = should_bundle_update?
T.unsafe(ENV).merge!(env)

unless should_update
unless should_update && !force_install
Bundler::CLI::Install.new({}).run
correct_relative_remote_paths if @custom_lockfile.exist?
return env
Expand All @@ -265,6 +265,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]) }
Expand Down
35 changes: 35 additions & 0 deletions test/setup_bundler_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit da83fae

Please sign in to comment.