From 36370f2ab7f636141d6475761e8db1e4d092b36a Mon Sep 17 00:00:00 2001 From: Jonas Arvidsson Date: Sun, 25 Feb 2024 10:22:22 +0100 Subject: [PATCH] [Fix #12695] Handle `Include` from inherited file in parent directory When we inherit configuration from a file in a parent or ancestor directory, and that file is called `.rubocop.yml`, the paths in its Include parameters are interpreted as being relative to the file, or rather its directory. This is specific for file names starting with `.rubocop`. The problem is that file name matching that we do when searching for target files to inspect doesn't work for patterns that start with `..`. Solve the problem by matching absolute paths in these corner cases. --- changelog/fix_config_include_bug.md | 1 + lib/rubocop/path_util.rb | 8 ++++++-- spec/rubocop/cli_spec.rb | 25 +++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 changelog/fix_config_include_bug.md diff --git a/changelog/fix_config_include_bug.md b/changelog/fix_config_include_bug.md new file mode 100644 index 000000000000..c81acd7c1b86 --- /dev/null +++ b/changelog/fix_config_include_bug.md @@ -0,0 +1 @@ +* [#12695](https://github.com/rubocop/rubocop/issues/12695): Fix bug in `Include` from inherited file in a parent directory. ([@jonas054][]) diff --git a/lib/rubocop/path_util.rb b/lib/rubocop/path_util.rb index d804e658dbbf..5907a109b13a 100644 --- a/lib/rubocop/path_util.rb +++ b/lib/rubocop/path_util.rb @@ -44,7 +44,7 @@ def smart_path(path) end end - # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity + # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity def match_path?(pattern, path) case pattern when String @@ -52,6 +52,10 @@ def match_path?(pattern, path) if pattern == path true elsif glob?(pattern) + # File name matching doesn't really work with relative patterns the start with "..". We + # get around that problem by converting the pattern to an absolute path. + pattern = File.expand_path(pattern) if pattern.start_with?('..') + File.fnmatch?(pattern, path, File::FNM_PATHNAME | File::FNM_EXTGLOB) end @@ -66,7 +70,7 @@ def match_path?(pattern, path) end end end - # rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity + # rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity # Returns true for an absolute Unix or Windows path. def absolute?(path) diff --git a/spec/rubocop/cli_spec.rb b/spec/rubocop/cli_spec.rb index 20ee2daf65d5..77ffe8d566cc 100644 --- a/spec/rubocop/cli_spec.rb +++ b/spec/rubocop/cli_spec.rb @@ -1113,6 +1113,31 @@ def meow_at_4am? abs('regexp')]) end + context 'when a .rubocop.yml is included from an ancestor directory' do + before do + create_file('child/grandkid/.rubocop.yml', <<~YAML) + inherit_from: + - ../../.rubocop.yml + YAML + end + + context 'and it specifies an Include pattern' do + before do + create_file('.rubocop.yml', <<~YAML) + AllCops: + Include: + - "**/*.rbi" + YAML + end + + it 'finds files included through inheritance' do + create_file('child/grandkid/file.rbi', 'x=0') + Dir.chdir('child/grandkid') { expect(cli.run(['-L'])).to eq(0) } + expect($stdout.string).to eq("file.rbi\n") + end + end + end + it 'ignores excluded files' do create_file('example.rb', ['x = 0', 'puts x']) create_file('regexp.rb', ['x = 0', 'puts x'])