Skip to content

Commit

Permalink
Make sure to run bundle install even when not altering the custom bundle
Browse files Browse the repository at this point in the history
  • Loading branch information
vinistock committed Jul 17, 2023
1 parent 71d3fcf commit 53a6e07
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 23 deletions.
54 changes: 36 additions & 18 deletions lib/ruby_lsp/setup_bundler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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

Expand Down Expand Up @@ -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")
33 changes: 28 additions & 5 deletions test/setup_bundler_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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")
Expand All @@ -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
Expand All @@ -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

0 comments on commit 53a6e07

Please sign in to comment.