From f08165dd149341cf7fd8f1879c693babaa98b884 Mon Sep 17 00:00:00 2001 From: Jarek Radosz Date: Mon, 18 May 2020 02:21:43 +0200 Subject: [PATCH] Fix resolving `inherit_gem` in remote configs 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. --- CHANGELOG.md | 2 ++ lib/rubocop/config_loader_resolver.rb | 10 +++++++++ spec/rubocop/config_loader_spec.rb | 31 ++++++++++++++++++++++++++- 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e689b7ca109..343f5550fe7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 @@ -4538,3 +4539,4 @@ [@jeffcarbs]: https://github.com/jeffcarbs [@laurmurclar]: https://github.com/laurmurclar [@jethrodaniel]: https://github.com/jethrodaniel +[@CvX]: https://github.com/CvX diff --git a/lib/rubocop/config_loader_resolver.rb b/lib/rubocop/config_loader_resolver.rb index 76230de346c..ef059c2ab6c 100644 --- a/lib/rubocop/config_loader_resolver.rb +++ b/lib/rubocop/config_loader_resolver.rb @@ -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 diff --git a/spec/rubocop/config_loader_spec.rb b/spec/rubocop/config_loader_spec.rb index 0043452a703..b9794a88e4c 100644 --- a/spec/rubocop/config_loader_spec.rb +++ b/spec/rubocop/config_loader_spec.rb @@ -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", @@ -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' }