Skip to content

Commit 2ec40a1

Browse files
committed
Avoid running bundle install unless necessary
1 parent 2d23e54 commit 2ec40a1

File tree

4 files changed

+40
-44
lines changed

4 files changed

+40
-44
lines changed

lib/ruby_lsp/requests/support/rubocop_runner.rb

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,22 @@
88
return
99
end
1010

11-
# Ensure that RuboCop is available
11+
# Remember to update the version in the documentation (usage/dependency-compatibility section) if you change this
12+
# Ensure that RuboCop is at least version 1.4.0
1213
begin
13-
require "rubocop"
14+
gem("rubocop", ">= 1.4.0")
1415
rescue LoadError
16+
$stderr.puts "Incompatible RuboCop version. Ruby LSP requires >= 1.4.0"
1517
return
1618
end
1719

18-
# Remember to update the version in the documentation (usage/dependency-compatibility section) if you change this
19-
# Ensure that RuboCop is at least version 1.4.0
20+
# Ensure that RuboCop is available
2021
begin
21-
gem("rubocop", ">= 1.4.0")
22+
require "rubocop"
2223
rescue LoadError
23-
$stderr.puts "Incompatible RuboCop version. Ruby LSP requires >= 1.4.0"
2424
return
25+
rescue StandardError => e
26+
$stderr.puts "Failed to load RuboCop: #{e.full_message}"
2527
end
2628

2729
if RuboCop.const_defined?(:LSP) # This condition will be removed when requiring RuboCop >= 1.61.

lib/ruby_lsp/server.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1435,6 +1435,8 @@ def compose_bundle(message)
14351435

14361436
#: -> void
14371437
def update_server
1438+
return unless @global_state.enabled_feature?(:launcher)
1439+
14381440
launch_bundle_compose("Trying to update server") do |stderr, status|
14391441
if status&.exitstatus == 0
14401442
send_log_message("Successfully updated the server")

lib/ruby_lsp/setup_bundler.rb

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -260,13 +260,36 @@ def run_bundle_install_directly(env, force_install: false)
260260

261261
# The ENV can only be merged after checking if an update is required because we depend on the original value of
262262
# ENV["BUNDLE_GEMFILE"], which gets overridden after the merge
263-
should_update = should_bundle_update?
263+
FileUtils.touch(@custom_dir + "needs_update") if should_bundle_update?
264264
ENV.merge!(env)
265265

266+
$stderr.puts("Ruby LSP> Checking if the composed bundle is satisfied...")
267+
definition = Bundler.definition
268+
definition.validate_runtime!
269+
definition.check!
270+
missing_gems = definition.missing_specs
271+
272+
unless missing_gems.empty?
273+
$stderr.puts(<<~MESSAGE)
274+
Ruby LSP> Running bundle install because the following gems are not installed:
275+
#{missing_gems.map { |g| "#{g.name}: #{g.version}" }.join("\n")}
276+
MESSAGE
277+
278+
bundle_install
279+
end
280+
281+
$stderr.puts("Ruby LSP> Bundle already satisfied")
282+
env
283+
rescue => e
284+
$stderr.puts("Ruby LSP> Running bundle install because #{e.message}")
285+
bundle_install
286+
env
287+
end
288+
289+
#: -> void
290+
def bundle_install
266291
Bundler::CLI::Install.new({ "no-cache" => true }).run
267292
correct_relative_remote_paths if @custom_lockfile.exist?
268-
FileUtils.touch(@custom_dir + "needs_update") if should_update
269-
env
270293
end
271294

272295
#: (Hash[String, String]) -> Hash[String, String]

test/setup_bundler_test.rb

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,7 @@ def test_invoke_cli_calls_bundler_directly_for_install
694694
mock_install = mock("install")
695695
mock_install.expects(:run)
696696
Bundler::CLI::Install.expects(:new).with({ "no-cache" => true }).returns(mock_install)
697+
Bundler::Definition.any_instance.expects(:check!).raises(StandardError.new("missing gems"))
697698
RubyLsp::SetupBundler.new(dir, launcher: true).setup!
698699
end
699700
end
@@ -728,6 +729,8 @@ def test_invoke_cli_calls_bundler_directly_for_update
728729
{ conservative: true },
729730
["ruby-lsp", "debug", "prism"],
730731
).returns(mock_update)
732+
733+
FileUtils.touch(File.join(dir, ".ruby-lsp", "needs_update"))
731734
RubyLsp::SetupBundler.new(dir, launcher: true).setup!
732735
end
733736
end
@@ -749,6 +752,7 @@ def test_progress_is_printed_to_stderr
749752
system("bundle install")
750753
end
751754

755+
Bundler::Definition.any_instance.expects(:check!).raises(StandardError.new("missing gems"))
752756
stdout, stderr = capture_subprocess_io do
753757
RubyLsp::SetupBundler.new(dir, launcher: true).setup!
754758
end
@@ -844,41 +848,6 @@ def test_is_resilient_to_gemfile_changes_in_the_middle_of_setup
844848
end
845849
end
846850

847-
def test_update_does_not_fail_if_gems_are_uninstalled
848-
Dir.mktmpdir do |dir|
849-
Dir.chdir(dir) do
850-
File.write(File.join(dir, "Gemfile"), <<~GEMFILE)
851-
source "https://rubygems.org"
852-
gem "rdoc"
853-
GEMFILE
854-
855-
capture_subprocess_io do
856-
Bundler.with_unbundled_env do
857-
system("bundle install")
858-
run_script(dir)
859-
860-
mock_update = mock("update")
861-
mock_update.expects(:run).raises(Bundler::GemNotFound.new("rdoc"))
862-
require "bundler/cli/update"
863-
Bundler::CLI::Update.expects(:new).with(
864-
{ conservative: true },
865-
["ruby-lsp", "debug", "prism"],
866-
).returns(mock_update)
867-
868-
mock_install = mock("install")
869-
mock_install.expects(:run)
870-
require "bundler/cli/install"
871-
Bundler::CLI::Install.expects(:new).with({ "no-cache" => true }).returns(mock_install)
872-
873-
RubyLsp::SetupBundler.new(dir, launcher: true).setup!
874-
end
875-
end
876-
877-
refute_path_exists(File.join(".ruby-lsp", "install_error"))
878-
end
879-
end
880-
end
881-
882851
def test_only_returns_environment_if_bundle_was_composed_ahead_of_time
883852
Dir.mktmpdir do |dir|
884853
Dir.chdir(dir) do

0 commit comments

Comments
 (0)