Skip to content

Commit

Permalink
Handle gems installed with --user-install (#27)
Browse files Browse the repository at this point in the history
When you install gems with `--user-install`, they will go in `~/.gem`
instead of in, e.g. `~/.rbenv` (or wherever your default GEM_PATH is).

This is a relatively uncommon way for gems to be installed, but it's
technically supported by bundler & rubygems, and it causes issues with
`uncruft`'s ability to resolve `$GEM_HOME` in ignorefile entries. This
PR adds an additional check against `Gem.user_dir` and treats it as
equivalent to `$GEM_HOME` (since the ignorefile is designed to work
across multiple systems, and should not care where the gems are
installed).
  • Loading branch information
smudge authored Jun 25, 2024
1 parent d43df5c commit 212b717
Show file tree
Hide file tree
Showing 7 changed files with 26 additions and 8 deletions.
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
uncruft (0.4.0)
uncruft (0.5.0)
railties (>= 6.1.0)

GEM
Expand Down
2 changes: 1 addition & 1 deletion gemfiles/rails_6_1.gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: ..
specs:
uncruft (0.4.0)
uncruft (0.5.0)
railties (>= 6.1.0)

GEM
Expand Down
2 changes: 1 addition & 1 deletion gemfiles/rails_7_0.gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: ..
specs:
uncruft (0.4.0)
uncruft (0.5.0)
railties (>= 6.1.0)

GEM
Expand Down
2 changes: 1 addition & 1 deletion gemfiles/rails_7_1.gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: ..
specs:
uncruft (0.4.0)
uncruft (0.5.0)
railties (>= 6.1.0)

GEM
Expand Down
10 changes: 9 additions & 1 deletion lib/uncruft/deprecation_handler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ def normalize_callstack_path(message)
message.gsub!(gem_home, '$GEM_PATH')
end

if (user_install = user_install(message)).present?
message.gsub!(user_install, '$GEM_PATH')
end

if message.include?(bin_dir)
message.gsub!(bin_dir, '$BIN_PATH')
end
Expand All @@ -70,7 +74,11 @@ def remove_line_number(message)
end

def gem_home(message)
message.match(%r{(?i:c)alled from( .+ at)? (#{ENV['GEM_HOME']}/(.+/)*gems)})&.[](2) # rubocop:disable Style/FetchEnvVar
message.match(%r{(?i:c)alled from( .+ at)? (#{ENV.fetch('GEM_HOME', nil)}/(.+/)*gems)})&.[](2).presence
end

def user_install(message)
message.match(%r{(?i:c)alled from( .+ at)? (#{Gem.user_dir}/(.+/)*gems)})&.[](2).presence
end

def absolute_path(message)
Expand Down
2 changes: 1 addition & 1 deletion lib/uncruft/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module Uncruft
VERSION = '0.4.0'
VERSION = '0.5.0'
end
14 changes: 12 additions & 2 deletions spec/uncruft/deprecation_handler_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
let(:expected_ignorefile_entry) { 'Warning: BAD called from <global scope> at $BIN_PATH/rake' }

before do
allow(RbConfig::CONFIG).to receive(:[]).and_call_original
allow(RbConfig::CONFIG).to receive(:[]).with('bindir').and_return bin_dir
end

Expand All @@ -114,8 +115,9 @@
let(:expected_ignorefile_entry) { "Warning: BAD called from <something> at $GEM_PATH/chicken/nuggets.rb" }

before do
allow(ENV).to receive(:[]).and_call_original
allow(ENV).to receive(:[]).with('GEM_HOME').and_return('/banana/banana/banana')
allow(ENV).to receive(:fetch).and_call_original
allow(ENV).to receive(:fetch).with('GEM_HOME', nil).and_return('/banana/banana/banana')
allow(Gem).to receive(:user_dir).and_return('/apple/apple/apple')
end

it 'sanitizes the message and raises an error' do
Expand All @@ -130,6 +132,14 @@
end
end

context 'when gem is installed in the --user-install path' do
let(:absolute_path) { Pathname.new('/apple/apple/apple/ohno/gems/chicken/nuggets.rb') }

it 'sanitizes the message and raises an error' do
expect { subject.call(message, '') }.to raise_error(RuntimeError, expected_error_message)
end
end

context 'when gem is vendored' do
let(:absolute_path) { Rails.root.join('vendor/cache/chicken/nuggets.rb') }

Expand Down

0 comments on commit 212b717

Please sign in to comment.