diff --git a/exe/ruby-lsp b/exe/ruby-lsp index 1c2833c2d..612e0f80f 100755 --- a/exe/ruby-lsp +++ b/exe/ruby-lsp @@ -37,6 +37,27 @@ parser = OptionParser.new do |opts| options[:launcher] = true end + opts.on("--update-server", "Update the Ruby LSP server") do + puts("Ruby LSP> Executing server update...") + require_relative "../lib/ruby_lsp/setup_bundler" + + begin + env = RubyLsp::SetupBundler.new(Dir.pwd, **options).setup! + rescue RubyLsp::SetupBundler::BundleNotLocked + warn("Project contains a Gemfile, but no Gemfile.lock. Run `bundle install` to lock gems") + exit(78) + end + + bundler_path = File.join(Gem.default_bindir, "bundle") + base_command = (!Gem.win_platform? && File.exist?(bundler_path) ? "#{Gem.ruby} #{bundler_path}" : "bundle").dup + + if env["BUNDLER_VERSION"] + base_command << " _#{env["BUNDLER_VERSION"]}_" + end + + exit(exec(env, "#{base_command} update ruby-lsp".strip)) + end + opts.on("-h", "--help", "Print this help") do puts opts.help puts diff --git a/test/integration_test.rb b/test/integration_test.rb index 3fdc4b5a6..6890035ca 100644 --- a/test/integration_test.rb +++ b/test/integration_test.rb @@ -333,6 +333,41 @@ def test_launch_mode_retries_if_setup_failed_after_successful_install end end + def test_update_server_command + in_temp_dir do |dir| + File.write(File.join(dir, "Gemfile"), <<~RUBY) + source "https://rubygems.org" + gem "stringio" + RUBY + + lockfile_contents = <<~LOCKFILE + GEM + remote: https://rubygems.org/ + specs: + stringio (3.1.7) + + PLATFORMS + arm64-darwin-23 + ruby + + DEPENDENCIES + stringio + + BUNDLED WITH + 2.5.7 + LOCKFILE + File.write(File.join(dir, "Gemfile.lock"), lockfile_contents) + + Bundler.with_unbundled_env do + stdout, _ = capture_subprocess_io do + system(File.join(@root, "exe", "ruby-lsp"), "--update-server") + end + + assert_includes(stdout, "Executing server update...") + end + end + end + private def launch(workspace_path, exec = "ruby-lsp-launcher", extra_env = {})