Skip to content

Commit

Permalink
[Fix rubocop#3396] Concise error when config. file not found
Browse files Browse the repository at this point in the history
Instead of a stack trace, prints a friendly (concise) message
to stderr when a configuration file, e.g. inherit_from, cannot
be found.

We use the constant Errno::ENOENT because it is present on
all major operating systems. According to the ruby documenation,
there may be some odd platforms that do not support this standard.
If we find that someone is using rubocop on such a platform, we
can rescue SystemCallError instead, but that will make it hard
to exit with the correct exit code.
  • Loading branch information
jaredbeck committed Oct 31, 2017
1 parent 5ecab46 commit 94e0574
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 14 deletions.
2 changes: 1 addition & 1 deletion .rubocop_todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Metrics/AbcSize:
# Offense count: 37
# Configuration parameters: CountComments.
Metrics/ClassLength:
Max: 180
Max: 186

# Offense count: 157
# Configuration parameters: CountComments.
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Bug fixes

* [#3396](https://github.com/bbatsov/rubocop/issues/3396): Concise error when config. file not found. ([@jaredbeck][])
* [#4881](https://github.com/bbatsov/rubocop/issues/4881): Fix a false positive for `Performance/HashEachMethods` when unused argument(s) exists in other blocks. ([@pocke][])
* [#4883](https://github.com/bbatsov/rubocop/pull/4883): Fix auto-correction for `Performance/HashEachMethods`. ([@pocke][])
* [#4896](https://github.com/bbatsov/rubocop/pull/4896): Fix Style/DateTime wrongly triggered on classes `...::DateTime`. ([@dpostorivo][])
Expand Down
12 changes: 11 additions & 1 deletion lib/rubocop/config_loader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ def transform(config)
end

def load_yaml_configuration(absolute_path)
yaml_code = IO.read(absolute_path, encoding: Encoding::UTF_8)
yaml_code = read_file(absolute_path)
hash = yaml_safe_load(yaml_code, absolute_path) || {}

puts "configuration from #{absolute_path}" if debug?
Expand All @@ -223,6 +223,16 @@ def load_yaml_configuration(absolute_path)
hash
end

# Read the specified file, or exit with a friendly, concise message on
# stderr. Care is taken to use the standard OS exit code for a "file not
# found" error.
def read_file(absolute_path)
IO.read(absolute_path, encoding: Encoding::UTF_8)
rescue Errno::ENOENT
warn(format('Configuration file not found: %s', absolute_path))
exit(Errno::ENOENT::Errno)
end

def yaml_safe_load(yaml_code, filename)
if YAML.respond_to?(:safe_load) # Ruby 2.1+
if defined?(SafeYAML) && SafeYAML.respond_to?(:load)
Expand Down
26 changes: 14 additions & 12 deletions spec/rubocop/config_loader_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -548,18 +548,6 @@ class FilePath < Cop
end
end

context 'when a file inherits from a non http/https url' do
let(:file_path) { '.rubocop.yml' }

before do
create_file(file_path, ['inherit_from: c:\\\\foo\\bar.yml'])
end

it 'fails to load the resulting path' do
expect { configuration_from_file }.to raise_error(Errno::ENOENT)
end
end

context 'EnabledByDefault / DisabledByDefault' do
def cop_enabled?(cop_class)
configuration_from_file.for_cop(cop_class).fetch('Enabled')
Expand Down Expand Up @@ -783,6 +771,20 @@ def cop_enabled?(cop_class)
end
end
end

context 'when the file does not exist' do
let(:configuration_path) { 'file_that_does_not_exist.yml' }

it 'prints a friendly (concise) message to stderr and exits' do
expect { load_file }.to(
output(/Configuration file not found/).to_stderr.and(
raise_error(SystemExit) do |e|
expect(e.status).to(eq(Errno::ENOENT::Errno))
end
)
)
end
end
end

describe '.merge' do
Expand Down

0 comments on commit 94e0574

Please sign in to comment.