Skip to content

Commit

Permalink
Fix resolving inherit_gem in remote configs
Browse files Browse the repository at this point in the history
When a file inherits from a url inheriting from a gem, like so:

```yaml
# .rubocop.yml
inherit_from: http://example.com/default.yml
```

```yaml
# http://example.com/default.yml
inherit_gem:
    somegem: default.yml
```

```yaml
# somegem's default.yml
Layout/LineLength:
    Max: 48
```

Rubocop would then incorrectly try to resolve a URL like this:

`http://example.com//private/var/folders/69/bjrqv8v1225f7yqnxknm3fb80000gn/T/d20200518-94245-6dqeew/work/gems/somegem/default.yml`

With this change, local gem paths are no longer taken by mistake for relative remote paths.
  • Loading branch information
CvX committed May 25, 2020
1 parent 8a383ac commit f08165d
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -26,6 +26,7 @@
* [#7886](https://github.com/rubocop-hq/rubocop/issues/7886): Fix a bug in `AllowComments` logic in `Lint/SuppressedException`. ([@jonas054][])
* [#7991](https://github.com/rubocop-hq/rubocop/issues/7991): Fix an error for `Layout/EmptyLinesAroundAttributeAccessor` when attribute method is method chained. ([@koic][])
* [#7993](https://github.com/rubocop-hq/rubocop/issues/7993): Fix a false positive for `Migration/DepartmentName` when a disable comment contains an unexpected character for department name. ([@koic][])
* [#7990](https://github.com/rubocop-hq/rubocop/issues/7990): Fix resolving `inherit_gem` in remote configs. ([@CvX][])

### Changes

Expand Down Expand Up @@ -4538,3 +4539,4 @@
[@jeffcarbs]: https://github.com/jeffcarbs
[@laurmurclar]: https://github.com/laurmurclar
[@jethrodaniel]: https://github.com/jethrodaniel
[@CvX]: https://github.com/CvX
10 changes: 10 additions & 0 deletions lib/rubocop/config_loader_resolver.rb
Expand Up @@ -171,10 +171,20 @@ def base_configs(path, inherit_from, file)

def inherited_file(path, inherit_from, file)
if remote_file?(inherit_from)
# A remote configuration, e.g. `inherit_from: http://example.com/rubocop.yml`.
RemoteConfig.new(inherit_from, File.dirname(path))
elsif Pathname.new(inherit_from).absolute?
# An absolute path to a config, e.g. `inherit_from: /Users/me/rubocop.yml`.
# The path may come from `inherit_gem` option, where a gem name is expanded
# to an absolute path to that gem.
print 'Inheriting ' if ConfigLoader.debug?
inherit_from
elsif file.is_a?(RemoteConfig)
# A path relative to a URL, e.g. `inherit_from: configs/default.yml`
# in a config included with `inherit_from: http://example.com/rubocop.yml`
file.inherit_from_remote(inherit_from, path)
else
# A local relative path, e.g. `inherit_from: default.yml`
print 'Inheriting ' if ConfigLoader.debug?
File.expand_path(inherit_from, File.dirname(path))
end
Expand Down
31 changes: 30 additions & 1 deletion spec/rubocop/config_loader_spec.rb
Expand Up @@ -781,7 +781,7 @@ class Loop < Cop

context 'when a file inherits from a known gem' do
let(:file_path) { '.rubocop.yml' }
let(:gem_root) { 'gems' }
let(:gem_root) { File.expand_path('gems') }

before do
create_file("#{gem_root}/gemone/config/rubocop.yml",
Expand Down Expand Up @@ -851,6 +851,35 @@ class Loop < Cop
end
end

context 'when a file inherits from a url inheriting from a gem' do
let(:file_path) { '.rubocop.yml' }
let(:cache_file) { '.rubocop-http---example-com-default-yml' }
let(:gem_root) { File.expand_path('gems') }
let(:gem_name) { 'somegem' }

before do
create_file(file_path, ['inherit_from: http://example.com/default.yml'])

stub_request(:get, %r{example.com/default})
.to_return(status: 200, body: "inherit_gem:\n #{gem_name}: default.yml")

create_file("#{gem_root}/#{gem_name}/default.yml", ["Layout/LineLength:\n Max: 48"])

mock_spec = OpenStruct.new(gem_dir: File.join(gem_root, gem_name))
allow(Gem::Specification).to receive(:find_by_name)
.with(gem_name).and_return(mock_spec)
allow(Gem).to receive(:path).and_return([gem_root])
end

after do
File.unlink cache_file if File.exist? cache_file
end

it 'resolves the inherited config' do
expect(configuration_from_file['Layout/LineLength']['Max']).to eq(48)
end
end

context 'when a file inherits from a url' do
let(:file_path) { '.rubocop.yml' }
let(:cache_file) { '.rubocop-http---example-com-rubocop-yml' }
Expand Down

0 comments on commit f08165d

Please sign in to comment.