ruby-lsp icon indicating copy to clipboard operation
ruby-lsp copied to clipboard

gem install fails if system installation directory is read-only

Open kepstin opened this issue 2 years ago • 6 comments

Operating System

Exherbo Linux

Ruby version

3.0

Project has a bundle

  • [X] Has bundle

Ruby version manager being used

no manager

Description

Using extension version 0.4.3. This is a regression from version 0.3.7. This issue appears to be related to Shopify/ruby-lsp#1640

I was using ruby-lsp with my operating system provided ruby, rather than ruby installed using a separate version manager. As a result, the standard gem installation directory is a system directory which is not writable by my user, and the extension initialization in 0.4.3 fails with the following error message:

Failed to setup the bundle: Command failed: gem install ruby-lsp ERROR: While executing gem ... (Gem::FilePermissionError) You don't have write permissions for the /usr/x86_64-pc-linux-gnu/lib/ruby/gems/3.0 directory.

This is expected; when using the system ruby, any extra per-user gems outside of bundle need to be installed somewhere else. But if I manually install the ruby-lsp gem with the command gem install --user-install ruby-lsp to try to work around this problem, gem prints this warning:

WARNING: You don't have /home/kepstin/.local/share/gem/ruby/3.0/bin in your PATH, gem executables will not run.

and indeed, the extension fails to start ruby-lsp:

[Error - 15:51:26] Ruby LSP client: couldn't create connection to server. Launching server using command ruby-lsp failed. Error: spawn ruby-lsp ENOENT Error restarting the server: undefined

But I don't want to install extra ruby gems in my "user-install" directory anyways, I'd prefer to have them privately installed in each project dir… so I tried to use the "Bundle Gemfile" configuration provided to replicate the behaviour of 0.3.7: I set "rubyLsp.bundleGemfile": ".ruby-lsp/Gemfile" and created the following Gemfile there:

source 'https://rubygems.org'
gem 'ruby-lsp'

I ran bundle config set --local path vendor/bundle in that directory to tell bundler to install the gems in that directory rather than in a system location, and did a bundle install.

But as far as I can tell, this configuration is non-functional; even with the Bundle Gemfile configuration set, the extension is still printing the same error message saying that it's trying to run gem install ruby-lsp. There's no code in the installOrUpdateServer function to handle checking if ruby-lsp is installed in a bundle environment, and also no code in start to handle starting ruby-lsp using bundler.

kepstin avatar Aug 02 '23 20:08 kepstin

Indeed, we have to execute the server with bundle exec if a user defined custom bundle is configured. And we need to not auto update the server gem, given that the configured bundle is not generated by us and should be managed by the user.

The associated PR should fix this.

vinistock avatar Aug 08 '23 18:08 vinistock

I've verified that the extension is successfully able to start the ruby-lsp command using bundleGemfile in version 0.4.4. This is sufficient workaround for the issue for my use case, but it doesn't fix the initial problem that I had opened the issue for, which is that the vscode ruby-lsp extension doesn't work "out of the box" when using a system ruby rather than ruby installed in a user home dir via a ruby version management tool. (I.e. with writable GEM_HOME).

It would be great to have it support installing the ruby-lsp gem into a user-writable directory when gem install ruby-lsp doesn't work. (Tho, honestly, it maybe should be done in all cases, to avoid adding an extra globally installed gem that doesn't get cleaned up if the vscode extension is removed)

I think the way this could be done would be to install the ruby-lsp gem in a global private data directory directory for the extension (rather than in each and every project dir) using bundler with a path configured; this should be done within the ExtensionContext.globalStorageUri directory so it gets properly cleaned up when the extension is updated/removed. This is similar to what e.g. the rust-analyzer vscode extension does - during initialization, it downloads a private copy of the rust-analyzer executable into its extension directory.

kepstin avatar Aug 09 '23 15:08 kepstin

I'd also like to note that the bundlerGemfile setting doesn't work with an absolute path right now, which I would like to use so multiple projects can share a single installation of the ruby-lsp gem.

kepstin avatar Aug 09 '23 15:08 kepstin

That's fair, I'm re-opening the issue. Given that the Ruby LSP is installed based on each Ruby version, it might not be very straight forward to just download it like Rust Analyzer does.

The Ruby LSP needs access to the project's bundle, which means it needs to be installed for the Ruby version being used in that project. For people using version managers, that could be several different versions, so we need to account for that when installing in VS Code's global storage path.

We'd be open to having this, but it needs to remain working seamlessly for people using version managers.

Concerning using an absolute bundle gemfile, that should be a straight forward fix. Do you want to take a stab at it?

vinistock avatar Aug 10 '23 18:08 vinistock

Fix for the absolute path for the custom bundle https://github.com/Shopify/vscode-ruby-lsp/pull/750.

vinistock avatar Aug 14 '23 14:08 vinistock

This issue is being marked as stale because there was no activity in the last 2 months

github-actions[bot] avatar Oct 14 '23 12:10 github-actions[bot]