From 6cc672d32af712e0b42e40310061a9b6525db16a Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Thu, 26 Jul 2018 22:14:50 +0900 Subject: [PATCH] Add `--init` option to `rubocop` command This PR adds `--init` option to `rubocop` command. ```console % mkdir example % cd /tmp/example % rubocop --init Writing new .rubocop.yml to /private/tmp/example/.rubocop.yml % cat .rubocop.yml # The behavior of RuboCop can be controlled via the .rubocop.yml # configuration file. It makes it possible to enable/disable # certain cops (checks) and to alter their behavior if they accept # any parameters. The file can be placed either in your home # directory or in some project directory. # # RuboCop will start looking for the configuration file in the directory # where the inspected file is and continue its way up to the root directory. # # See https://github.com/rubocop-hq/rubocop/blob/master/manual/configuration.md % rubocop --init # A warning will occur when .rubocop.yml already exists .rubocop.yml already exists at /private/tmp/example/.rubocop.yml ``` It may be good to add a simple commented examples of basic configuration in the future. First of all, this PR aims to generate .rubocop.yml which contains the following configuration URL. https://github.com/rubocop-hq/rubocop/blob/master/manual/configuration.md And the generated .rubocop.yml text is quoted from the above URL. --- CHANGELOG.md | 4 ++++ lib/rubocop/cli.rb | 44 ++++++++++++++++++++++++++++++++---- lib/rubocop/options.rb | 5 +++- manual/basic_usage.md | 1 + spec/rubocop/cli_spec.rb | 30 ++++++++++++++++++++++++ spec/rubocop/options_spec.rb | 1 + 6 files changed, 80 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b715bde3f2..e79836519db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## master (unreleased) +### New features + +* [#6928](https://github.com/rubocop-hq/rubocop/pull/6928): Add `--init` option for generate `.rubocop.yml` file in the current directory. ([@koic][]) + ### Bug fixes * [#6914](https://github.com/rubocop-hq/rubocop/issues/6914): [Fix #6914] Fix an error for `Rails/RedundantAllowNil` when with interpolations. ([@Blue-Pix][]) diff --git a/lib/rubocop/cli.rb b/lib/rubocop/cli.rb index ddf70dde53c..030f6c7abaa 100644 --- a/lib/rubocop/cli.rb +++ b/lib/rubocop/cli.rb @@ -41,10 +41,15 @@ def initialize # rubocop:disable Metrics/MethodLength, Metrics/AbcSize def run(args = ARGV) @options, paths = Options.new.parse(args) - validate_options_vs_config - act_on_options - apply_default_formatter - execute_runners(paths) + + if @options[:init] + init_dotfile + else + validate_options_vs_config + act_on_options + apply_default_formatter + execute_runners(paths) + end rescue ConfigNotFoundError, IncorrectCopNameError, OptionArgumentError => e warn e.message STATUS_ERROR @@ -132,6 +137,37 @@ def run_all_cops_auto_gen_config(line_length_contents, paths) result end + def init_dotfile + path = File.expand_path(ConfigLoader::DOTFILE) + + if File.exist?(ConfigLoader::DOTFILE) + warn Rainbow("#{ConfigLoader::DOTFILE} already exists at #{path}").red + + STATUS_ERROR + else + description = <<-DESC.strip_indent + # The behavior of RuboCop can be controlled via the .rubocop.yml + # configuration file. It makes it possible to enable/disable + # certain cops (checks) and to alter their behavior if they accept + # any parameters. The file can be placed either in your home + # directory or in some project directory. + # + # RuboCop will start looking for the configuration file in the directory + # where the inspected file is and continue its way up to the root directory. + # + # See https://github.com/rubocop-hq/rubocop/blob/master/manual/configuration.md + DESC + + File.open(ConfigLoader::DOTFILE, 'w') do |f| + f.write(description) + end + + puts "Writing new #{ConfigLoader::DOTFILE} to #{path}" + + STATUS_SUCCESS + end + end + def reset_config_and_auto_gen_file @config_store = ConfigStore.new @config_store.options_config = @options[:config] if @options[:config] diff --git a/lib/rubocop/options.rb b/lib/rubocop/options.rb index 6c75faabc34..3f24303b2e1 100644 --- a/lib/rubocop/options.rb +++ b/lib/rubocop/options.rb @@ -117,6 +117,8 @@ def add_auto_gen_options(opts) option(opts, '--no-auto-gen-timestamp') do @options[:no_auto_gen_timestamp] = true end + + option(opts, '--init') end def add_formatting_options(opts) @@ -435,7 +437,8 @@ module OptionsHelp parallel: ['Use available CPUs to execute inspection in', 'parallel.'], stdin: ['Pipe source from STDIN, using FILE in offense', - 'reports. This is useful for editor integration.'] + 'reports. This is useful for editor integration.'], + init: 'Generate a .rubocop.yml file in the current directory.' }.freeze end end diff --git a/manual/basic_usage.md b/manual/basic_usage.md index 1e8ac3c5759..3f8b3f17f26 100644 --- a/manual/basic_usage.md +++ b/manual/basic_usage.md @@ -117,6 +117,7 @@ Command flag | Description ` --force-exclusion` | Force excluding files specified in the configuration `Exclude` even if they are explicitly passed as arguments. `-h/--help` | Print usage information. ` --ignore-parent-exlusion` | Ignores all Exclude: settings from all .rubocop.yml files present in parent folders. This is useful when you are importing submodules when you want to test them without being affected by the parent module's rubocop settings. +` --init` | Generate a .rubocop.yml file in the current directory. `-l/--lint` | Run only lint cops. `-L/--list-target-files` | List all files RuboCop will inspect. ` --no-auto-gen-timestamp` | Don't include the date and time when --auto-gen-config was run in the config file it generates diff --git a/spec/rubocop/cli_spec.rb b/spec/rubocop/cli_spec.rb index 36b428460e1..55a8d88e2e3 100644 --- a/spec/rubocop/cli_spec.rb +++ b/spec/rubocop/cli_spec.rb @@ -209,6 +209,36 @@ def and_with_args RESULT end + describe 'Specify `--init` option to `rubocop` command' do + context 'when .rubocop.yml does not exist' do + it 'generate a .rubocop.yml file' do + expect(cli.run(['--init'])).to eq(0) + expect($stdout.string).to start_with('Writing new .rubocop.yml to') + expect(IO.read('.rubocop.yml')).to eq(<<-YAML.strip_indent) + # The behavior of RuboCop can be controlled via the .rubocop.yml + # configuration file. It makes it possible to enable/disable + # certain cops (checks) and to alter their behavior if they accept + # any parameters. The file can be placed either in your home + # directory or in some project directory. + # + # RuboCop will start looking for the configuration file in the directory + # where the inspected file is and continue its way up to the root directory. + # + # See https://github.com/rubocop-hq/rubocop/blob/master/manual/configuration.md + YAML + end + end + + context 'when .rubocop.yml already exists' do + it 'fails with an error message' do + create_empty_file('.rubocop.yml') + + expect(cli.run(['--init'])).to eq(2) + expect($stderr.string).to start_with('.rubocop.yml already exists at') + end + end + end + context 'when --auto-correct is given' do it 'does not trigger UnneededCopDisableDirective due to ' \ 'lines moving around' do diff --git a/spec/rubocop/options_spec.rb b/spec/rubocop/options_spec.rb index 6f3e5727d30..58ccf202d54 100644 --- a/spec/rubocop/options_spec.rb +++ b/spec/rubocop/options_spec.rb @@ -61,6 +61,7 @@ def abs(path) --no-auto-gen-timestamp Do not include the date and time when the --auto-gen-config was run in the file it generates. + --init Generate a .rubocop.yml file in the current directory. -f, --format FORMATTER Choose an output formatter. This option can be specified multiple times to enable multiple formatters at the same time.