SublimeLinter / SublimeLinter-rubocop

SublimeLinter 3 plugin for Ruby, using rubocop.
MIT License
159 stars 40 forks source link

/usr/bin/ruby: No such file or directory -- bundle (LoadError) #53

Closed revolter closed 5 years ago

revolter commented 6 years ago

Having these Sublime Linter settings:

// SublimeLinter Settings - User
{
    "debug": true,
    "linters": {
        "rubocop": {
            "use_bundle_exec": true
        }
    },
    "paths": {
        "osx": [
            "~/.gems/bin"
        ]
    }
}

I still get /usr/bin/ruby: No such file or directory -- bundle (LoadError):

SublimeLinter: #7 SublimeLinter.sublime-package:747: 'rubocop' is linting 'main.rb'
SublimeLinter: #7 SublimeLinter.sublime-package:1045: rubocop: main.rb ['/usr/bin/ruby', '-S', 'bundle', 'exec', 'rubocop', '--format', 'emacs', '--force-exclusion', '--stdin', '/path/to/main.rb']
SublimeLinter: #7 SublimeLinter.sublime-package:1048: rubocop: cwd: /path/to
SublimeLinter: #7 SublimeLinter.sublime-package:774: rubocop output:
    /usr/bin/ruby: No such file or directory -- bundle (LoadError)
SublimeLinter: #7 SublimeLinter.sublime-package:815: rubocop: No match for line: '/usr/bin/ruby: No such file or directory -- bundle (LoadError)'

Bundler was installed using the official instructions and is available in the PATH:

> which rubocop
/Users/revolt/.gems/bin/rubocop
kaste commented 6 years ago

Hi 👋

I think the we don't have any ruby people here in the org anymore. When you see the log

cmd : ['/usr/bin/ruby', '-S', 'bundle', 'exec', 'rubocop', '--format', 'emacs', '--force-exclusion', '--stdin', '/path/to/main.rb']
cwd: [REDACTED]

The cmd is what we actually run here. (Join it via ' ' then it is less confusing.) What would be the correct command? How do you invoke this on your Terminal?

Can you look at https://github.com/SublimeLinter/SublimeLinter-rubocop/pull/52#issuecomment-375776227 where I also ask some questions?

revolter commented 6 years ago

Hi, the command would simply be bundle exec rubocop --format emacs --force-exclusion /path/to/main.rb, but /usr/bin/ruby -S bundle exec rubocop --format emacs --force-exclusion /path/to/main.rb (without the --stdin part) also works.

Leaving the --stdin part only hangs the command indefinitely, so this issue looks like it's caused by another problem. It looks like the PATH isn't loaded properly.

kaste commented 6 years ago

Okay, if the cmd is okay. You then have to change the execution env. I saw you set paths which is discouraged using SL4 (bc it is a global setting). Use a linter setting (these settings can be changed per project), like so:

  "linters": {
     "rubocop": {
         "env": {
            "PATH": "my/additional/path/:$PATH"
         },

So you prepend additional/path to the current one. Does something like that make sense? (Obviously you can set other env variables here too.)

kaste commented 6 years ago

(If you leave --stdin you must cat something in.)

kaste commented 6 years ago

Maybe stupid but would just rubocop --format emacs --force-exclusion /path/to/main.rb also work given a correct PATH. Say rubocop is globally installed, just like eslint . works if it is globally installed?

revolter commented 6 years ago

Use a linter setting (these settings can be changed per project)

The paths part I took from the official docs, so the instructions should be updated.

Changing the SublimeLinter preferences to:

{
    "debug": true,
    "linters": {
        "rubocop": {
            "env": {
                "PATH": "~/.gems/bin:$PATH"
            },
            "use_bundle_exec": true
        }
    }
}

throws this:

SublimeLinter: #4 SublimeLinter.sublime-package:104: PATH:
    /usr/local/bin
    /usr/bin
    /bin
    /usr/sbin
    /sbin
    /opt/X11/bin
SublimeLinter: #4 SublimeLinter.sublime-package:1044: rubocop: main.rb ['/usr/bin/ruby', '-S', 'bundle', 'exec', 'rubocop', '--format', 'emacs', '--force-exclusion', '--stdin', '/path/to/main.rb']
SublimeLinter: #4 SublimeLinter.sublime-package:1047: rubocop: cwd: /path/to
SublimeLinter: #4 SublimeLinter.sublime-package:773: rubocop output:
    /Library/Ruby/Site/2.3.0/rubygems.rb:271:in `find_spec_for_exe': can't find gem bundler (>= 0.a) (Gem::GemNotFoundException)
        from /Library/Ruby/Site/2.3.0/rubygems.rb:299:in `activate_bin_path'
        from /Users/revolt/.gems/bin/bundle:23:in `<main>'
SublimeLinter: #4 SublimeLinter.sublime-package:814: rubocop: No match for line: '/Library/Ruby/Site/2.3.0/rubygems.rb:271:in `find_spec_for_exe': can't find gem bundler (>= 0.a) (Gem::GemNotFoundException)'
SublimeLinter: #4 SublimeLinter.sublime-package:814: rubocop: No match for line: '  from /Library/Ruby/Site/2.3.0/rubygems.rb:299:in `activate_bin_path''
SublimeLinter: #4 SublimeLinter.sublime-package:814: rubocop: No match for line: '  from /Users/revolt/.gems/bin/bundle:23:in `<main>''

Maybe stupid but would just rubocop --format emacs --force-exclusion /path/to/main.rb also work given a correct PATH. Say rubocop is globally installed, just like eslint . works if it is globally installed?

bundle is used because I set use_bundle_exec to true. But disabling it still doesn't work:

SublimeLinter: #1 SublimeLinter.sublime-package:104: PATH:
    /Users/revolt/.gems/bin
    /usr/local/bin
    /usr/bin
    /bin
    /usr/sbin
    /sbin
    /opt/X11/bin
SublimeLinter: #1 SublimeLinter.sublime-package:1044: rubocop: main.rb ['/usr/bin/ruby', '-S', 'rubocop', '--format', 'emacs', '--force-exclusion', '--stdin', '/path/to/main.rb']
SublimeLinter: #1 SublimeLinter.sublime-package:1047: rubocop: cwd: /path/to
SublimeLinter: #1 SublimeLinter.sublime-package:773: rubocop output:
    /usr/bin/ruby: No such file or directory -- rubocop (LoadError)
SublimeLinter: #1 SublimeLinter.sublime-package:814: rubocop: No match for line: '/usr/bin/ruby: No such file or directory -- rubocop (LoadError)'

even though:

> which rubocop
/Users/revolt/.gems/bin/rubocop

And as you can see, SublimeLinter is printing the PATH which actually does contain /Users/revolt/.gems/bin.

(this second reply was tested first, so it was tested with the old paths in the preferences; changing it to env only causes it to crash with find_spec_for_exe': can't find gem rubocop)

kaste commented 6 years ago

I've made a minimal PR https://github.com/SublimeLinter/SublimeLinter-rubocop/pull/55

Usage info can be found over there.

burlesona commented 6 years ago

I've run into the same issue. At minimum it should start with /usr/bin/env ruby instead of /usr/bin/ruby, since the various ruby version managers etc. will work correctly if you use the env ruby instead of system.

saltvedt commented 6 years ago

Im using RVM, and by running import os; os.environ I saw that Sublime is using the wrong Ruby version (2.2.2 instead of 2.5.0).

So I tried installing rubocop on the older version:

$ rvm use 2.2.2
$ gem install rubocop
$ rvm use 2.5.0

And now SublimeLinter-rubocop works for me, even though Sublime is still working with the wrong environment.

(Version 4.2.1 of SublimeLinter and 2.0.4 of SublimeLinter-rubocop)

Issue might be related to this: https://github.com/SublimeLinter/SublimeLinter/issues/446

TomasBarry commented 6 years ago

FWIW: By looking at the output of import os; os.environ as suggested by @saltvedt, I noticed that the PATH environment variable was incorrect.

Running Sublime from the command line fixed the issue (https://stackoverflow.com/questions/13033915/sublime-text-is-running-with-an-incorrect-path-environment-variable).

mlangenberg commented 5 years ago

This might be related. I have a similar issue, seemingly caused by PATH being in the wrong order.

SublimeLinter: #2 util.py:132         PATH:
    /usr/local/Cellar/gettext/0.19.8.1/bin
    /usr/local/opt/mysql@5.7/bin
    ~/local/bin
    /usr/local/sbin
    /usr/local/bin
    /usr/bin
    /bin
    /usr/sbin
    /sbin
    ~/.rbenv/shims # <- correct ruby binary path
    /usr/local/Cellar/gettext/0.19.8.1/bin
    /usr/local/opt/mysql@5.7/bin
SublimeLinter: #2 linter.py:1305      Running ...

  ~/dev/my-project  (working dir)
  $ cat app/file.rb | /usr/bin/ruby -S rubocop --format emacs --force-exclusion --stdin
                      ^^^^^^^^^^^^^ /usr/bin in earlier PATH?

Of course running from a shell resolves to the correct binary.

# using fish shell
$ which ruby
~/.rbenv/shims/ruby

Mitigated with the following configuration, but shouldn't be needed.

// SublimeLinter Settings - User
{
  "paths": {
    "osx": [
      "~/.rbenv/shims"
    ]
  }
}
kaste commented 5 years ago

I saw that ordering issue before. Don't know why that happens for some users. (SublimeLinter should not be the cause here. Since we never figured a fix that works for all users, we decided to not ship any fix at all.)

A proposed fix can be found here https://github.com/SublimeLinter/SublimeLinter/pull/1509 This is pretty much a stand-alone fix that can be installed via copy/paste. See the instructions over there.

mlangenberg commented 5 years ago

Yeah, I didn't want to put the blame at SublimeLinter or SublimeLinter-rubocop. This was the only related issue I could find after messing around with it for too long and wanted to document it.

The good news is that after dropping in the fix, my PATH is correct within sublime.

SublimeLinter: #1 util.py:132         PATH:
    ~/.rbenv/shims
    /usr/local/Cellar/gettext/0.19.8.1/bin
    /usr/local/opt/mysql@5.7/bin
    ~/.rbenv/bin ~/local/bin /usr/local/sbin
    /usr/local/bin
    /usr/bin
    /bin
    /usr/sbin
    /sbin
    /usr/local/Cellar/gettext/0.19.8.1/bin
    /usr/local/opt/mysql@5.7/bin
    ~/.rbenv/shims
    ~/.rbenv/bin
    ~/local/bin
    /usr/local/sbin
SublimeLinter: #1 linter.py:1305      Running ...

  ~/dev/my-project  (working dir)
  $ cat app/file.rb | ~/.rbenv/shims/ruby -S rubocop --format emacs ...
                      ^^^^^^^^^^^^^^^^ 🎉              
joshmfrankel commented 5 years ago

Similar to @mlangenberg above, asdf users may experience similar issues.

Shell points to correctly shimmed binary

$ which rubocop
~/.asdf/shims/rubocop

SublimeLinter continues to point at /usr/bin/ruby

cat some_file_to_be_linted.rb | /usr/bin/ruby -S rubocop --format emacs --force-exclusion --stdin some_file_to_be_linted.rb
// Note that --stdin points incorrectly at a file and not the directory

I was unable to solve my issue using the "env": { "PATH": "~/.asdf/shims" }. Instead, I had to specify the executable directly:

"rubocop": {
  "disable": false,
  "args": [],
  "excludes": [],
  "executable": "~/.asdf/shims/rubocop"
}

Note in the above --stdin does not work correctly still. Instead it returns:

SublimeLinter: #21 linter.py:639      WARNING: rubocop output:
-s/--stdin requires exactly one path, relative to the root of the project. RuboCop will use this path to determine which cops are enabled (via eg. Include/Exclude), and so that certain cops like Naming/FileName can be checked.
kaste commented 5 years ago

One user noted (elsewhere) that using Sublime 3.2 the PATH is correct, and the patch https://github.com/SublimeLinter/SublimeLinter/pull/1509 is not necessary anymore. Maybe someone can try that, and report back.

The interesting (and suprising) part for this linter is that it always starts with ruby -S as command. This means SublimeLinter, the framework, never actually tries a simple which rubocop, instead it tries which ruby, and then does a /path/to/ruby -S rubocop.

@joshmfrankel Do you use the master version or my PR #55? I would suspect that it runs ~/.asdf/shims/rubocop -S rubocop if you set executable that way.

kaste commented 5 years ago

Closing since a new version of this plugin has 🚢 'ed right now.

Steven-Chang commented 5 years ago

Not sure 100% if this is related but this is how I fixed my Rubocop issues...