From db2eff6402312e9ecc89db7d7ce511549073ce40 Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Fri, 25 Feb 2022 20:26:27 -0800 Subject: [PATCH 01/53] Move from Travis CI to GitHub Actions (#770) --- .github/workflows/lint.yml | 29 +++++++++++++++++++++ .github/workflows/tests.yml | 52 +++++++++++++++++++++++++++++++++++++ .travis.yml | 24 ----------------- README.md | 3 +-- 4 files changed, 82 insertions(+), 26 deletions(-) create mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/tests.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..24baefc6 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,29 @@ +name: Lint +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + overcommit: + timeout-minutes: 10 + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.7 + bundler-cache: true + + - name: Prepare environment + run: | + git config --local user.email "gh-actions@example.com" + git config --local user.name "GitHub Actions" + bundle exec overcommit --sign + + - name: Run pre-commit checks + run: bundle exec overcommit --run diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 00000000..91ddb5b9 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,52 @@ +name: Tests +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + rspec: + timeout-minutes: 10 + runs-on: ${{ matrix.os }}-latest + + strategy: + matrix: + ruby-version: + - '2.6' + - '2.7' + - '3.0' + - '3.1' + os: + - ubuntu + - windows + + steps: + - uses: actions/checkout@v2 + + - name: Set up Ruby ${{ matrix.ruby-version }} + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby-version }} + bundler-cache: true + + - name: Run tests + run: bundle exec rspec + + - name: Code coverage reporting + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.github_token }} + flag-name: ruby${{ matrix.ruby-version }}-${{ matrix.os }} + parallel: true + + finish: + needs: rspec + runs-on: ubuntu-latest + + steps: + - name: Finalize code coverage report + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.github_token }} + parallel-finished: true diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 7b489462..00000000 --- a/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -language: ruby - -cache: bundler - -rvm: - - 2.4 - - 2.5 - - 2.6 - - 2.7 - - 3.0 - -before_script: - - git config --global user.email "travis@travis.ci" - - git config --global user.name "Travis CI" - -before_install: - - gem update --system - - gem install bundler - -script: - - bundle exec rspec - - bundle exec overcommit --sign - - bundle exec overcommit --sign pre-commit - - bundle exec overcommit --run diff --git a/README.md b/README.md index 36126a2c..0464e604 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ [![Gem Version](https://badge.fury.io/rb/overcommit.svg)](https://badge.fury.io/rb/overcommit) -[![Build Status](https://travis-ci.org/sds/overcommit.svg?branch=master)](https://travis-ci.org/sds/overcommit) -[![Windows Build Status](https://ci.appveyor.com/api/projects/status/umui038jlm597ryf?svg=true)](https://ci.appveyor.com/project/sds/overcommit) +[![Build Status](https://github.com/sds/overcommit/actions/workflows/tests.yml/badge.svg?branch=master)](https://github.com/sds/overcommit/actions/workflows/tests.yml/badge.svg?branch=master) [![Coverage Status](https://coveralls.io/repos/github/sds/overcommit/badge.svg?branch=master)](https://coveralls.io/github/sds/overcommit?branch=master) [![Maintainability](https://api.codeclimate.com/v1/badges/5da42f7f365e5fef6b4c/maintainability)](https://codeclimate.com/github/sds/overcommit/maintainability) [![Inline docs](http://inch-ci.org/github/sds/overcommit.svg?branch=master)](http://inch-ci.org/github/sds/overcommit) From c142cd27fbfcbf67907f2cb3d6710808af0b74d3 Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Fri, 25 Feb 2022 22:18:00 -0800 Subject: [PATCH 02/53] Fix configuration loading on Ruby 3.1 (#771) --- .github/workflows/lint.yml | 5 +- .github/workflows/tests.yml | 6 +- .projections.json | 10 --- .simplecov | 6 -- Gemfile | 4 +- appveyor.yml | 61 ------------------- lib/overcommit/cli.rb | 4 +- lib/overcommit/hook/pre_commit/php_lint.rb | 4 +- spec/overcommit/default_configuration_spec.rb | 6 +- .../hook/pre_commit/php_lint_spec.rb | 4 +- spec/overcommit/hook/pre_commit/phpcs_spec.rb | 8 +-- spec/overcommit/utils_spec.rb | 10 +-- spec/spec_helper.rb | 25 +++++--- template-dir/hooks/commit-msg | 9 ++- template-dir/hooks/overcommit-hook | 9 ++- template-dir/hooks/post-checkout | 9 ++- template-dir/hooks/post-commit | 9 ++- template-dir/hooks/post-merge | 9 ++- template-dir/hooks/post-rewrite | 9 ++- template-dir/hooks/pre-commit | 9 ++- template-dir/hooks/pre-push | 9 ++- template-dir/hooks/pre-rebase | 9 ++- template-dir/hooks/prepare-commit-msg | 9 ++- 23 files changed, 126 insertions(+), 117 deletions(-) delete mode 100644 .projections.json delete mode 100644 .simplecov delete mode 100644 appveyor.yml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 24baefc6..b1879f09 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -21,9 +21,10 @@ jobs: - name: Prepare environment run: | - git config --local user.email "gh-actions@example.com" - git config --local user.name "GitHub Actions" + git config --global user.email "gh-actions@example.com" + git config --global user.name "GitHub Actions" bundle exec overcommit --sign + bundle exec overcommit --sign pre-commit - name: Run pre-commit checks run: bundle exec overcommit --run diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 91ddb5b9..e57f5204 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,7 +19,6 @@ jobs: - '3.1' os: - ubuntu - - windows steps: - uses: actions/checkout@v2 @@ -31,7 +30,10 @@ jobs: bundler-cache: true - name: Run tests - run: bundle exec rspec + run: | + git config --global user.email "gh-actions@example.com" + git config --global user.name "GitHub Actions" + bundle exec rspec - name: Code coverage reporting uses: coverallsapp/github-action@master diff --git a/.projections.json b/.projections.json deleted file mode 100644 index 24f5ce34..00000000 --- a/.projections.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "lib/overcommit/*.rb": { - "alternate": "spec/overcommit/{}_spec.rb", - "type": "source" - }, - "spec/overcommit/*_spec.rb": { - "alternate": "lib/overcommit/{}.rb", - "type": "test" - } -} diff --git a/.simplecov b/.simplecov deleted file mode 100644 index 3cc40052..00000000 --- a/.simplecov +++ /dev/null @@ -1,6 +0,0 @@ -SimpleCov.start do - add_filter 'bin/' - add_filter 'libexec/' - add_filter 'spec/' - add_filter 'template-dir/' -end diff --git a/Gemfile b/Gemfile index d1cd3c37..ff22be0c 100644 --- a/Gemfile +++ b/Gemfile @@ -8,8 +8,8 @@ gemspec gem 'rspec', '~> 3.0' -# Generate coverage information in Travis builds -gem 'coveralls', '~> 0.8' +gem 'simplecov', '~> 0.21.0' +gem 'simplecov-lcov', '~> 0.8.0' # Pin RuboCop for Travis builds. gem 'rubocop', '0.82.0' diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index fcb90b95..00000000 --- a/appveyor.yml +++ /dev/null @@ -1,61 +0,0 @@ -version: "{build}" - -clone_depth: 1 - -environment: - matrix: - - RUBY_FOLDER_VERSION: "24-x64" - - RUBY_FOLDER_VERSION: "25-x64" - - RUBY_FOLDER_VERSION: "26-x64" -matrix: - fast_finish: true - -cache: - # Cache installed gems unless dependencies change - - vendor\bundle -> Gemfile,overcommit.gemspec - -install: - # Add ruby executables to PATH - - set PATH=C:\Ruby%RUBY_FOLDER_VERSION%\bin;%PATH% - - echo %PATH% - - # Print version and location for pre-installed grep - - grep --version - - where grep - - # Print version and location for pre-installed git - - git --version - - where git - - # Print version and location for pre-installed ruby - - ruby --version - - where ruby - - # Install latest version of RubyGems - - gem update --system --no-document - - gem --version - - where gem - - # Install latest Bundler to work around version issues - - gem install bundler:'< 2' --force - - where bundler - - # Install ruby dependencies - - bundle install --retry 3 --path vendor\bundle - -build: off - -before_test: - # Necessary for AuthorName and AuthorEmail pre-commit hooks to pass - - git config --global user.email "appveyor@appveyor.ci" - - git config --global user.name "Appveyor CI" - - # Ignore CRLF conversion warnings - - git config --global core.autocrlf true - - git config --global core.safecrlf false - -test_script: - - bundle exec rspec --tty --backtrace --color - - bundle exec overcommit --sign - - bundle exec overcommit --sign pre-commit - - bundle exec overcommit --run diff --git a/lib/overcommit/cli.rb b/lib/overcommit/cli.rb index d8b743a3..bc2ec994 100644 --- a/lib/overcommit/cli.rb +++ b/lib/overcommit/cli.rb @@ -94,7 +94,7 @@ def add_installation_options(opts) @options[:force] = true end - opts.on('-r [hook]', '--run [hook]', 'Run specified hook against all git tracked files. Defaults to `pre_commit`.') do |arg| + opts.on('-r [hook]', '--run [hook]', 'Run specified hook against all git tracked files. Defaults to `pre_commit`.') do |arg| # rubocop:disable Layout/LineLength @options[:action] = :run_all @options[:hook_to_run] = arg ? arg.to_s : 'run-all' end @@ -200,7 +200,7 @@ def sign def run_all empty_stdin = File.open(File::NULL) # pre-commit hooks don't take input - context = Overcommit::HookContext.create(@options[:hook_to_run], config, @arguments, empty_stdin) + context = Overcommit::HookContext.create(@options[:hook_to_run], config, @arguments, empty_stdin) # rubocop:disable Layout/LineLength config.apply_environment!(context, ENV) printer = Overcommit::Printer.new(config, log, context) diff --git a/lib/overcommit/hook/pre_commit/php_lint.rb b/lib/overcommit/hook/pre_commit/php_lint.rb index 3f70bfb2..f2ba2f24 100644 --- a/lib/overcommit/hook/pre_commit/php_lint.rb +++ b/lib/overcommit/hook/pre_commit/php_lint.rb @@ -4,9 +4,9 @@ module Overcommit::Hook::PreCommit # Runs `php -l` against any modified PHP files. class PhpLint < Base # Sample String - # rubocop:disable Metrics/LineLength + # rubocop:disable Layout/LineLength # PHP Parse error: syntax error, unexpected 'require_once' (T_REQUIRE_ONCE) in site/sumo.php on line 12 - # rubocop:enable Metrics/LineLength + # rubocop:enable Layout/LineLength MESSAGE_REGEX = /^(?.+)\:\s+(?.+) in (?.+) on line (?\d+)/.freeze def run diff --git a/spec/overcommit/default_configuration_spec.rb b/spec/overcommit/default_configuration_spec.rb index a86b1fe3..706af872 100644 --- a/spec/overcommit/default_configuration_spec.rb +++ b/spec/overcommit/default_configuration_spec.rb @@ -4,7 +4,11 @@ describe 'default configuration' do default_config = - YAML.load_file(Overcommit::ConfigurationLoader::DEFAULT_CONFIG_PATH).to_hash + begin + YAML.load_file(Overcommit::ConfigurationLoader::DEFAULT_CONFIG_PATH, aliases: true).to_hash + rescue ArgumentError + YAML.load_file(Overcommit::ConfigurationLoader::DEFAULT_CONFIG_PATH).to_hash + end Overcommit::Utils.supported_hook_types.each do |hook_type| hook_class = Overcommit::Utils.camel_case(hook_type) diff --git a/spec/overcommit/hook/pre_commit/php_lint_spec.rb b/spec/overcommit/hook/pre_commit/php_lint_spec.rb index aff0b97e..ec755345 100644 --- a/spec/overcommit/hook/pre_commit/php_lint_spec.rb +++ b/spec/overcommit/hook/pre_commit/php_lint_spec.rb @@ -26,13 +26,13 @@ context 'when php lint exits unsuccessfully' do before do # php -l prints the same to both stdout and stderr - # rubocop:disable Metrics/LineLength + # rubocop:disable Layout/LineLength sample_output = [ '', "Parse error: syntax error, unexpected '0' (T_LNUMBER), expecting variable (T_VARIABLE) or '{' or '$' in sample.php on line 3 ", 'Errors parsing invalid.php', ].join("\n") - # rubocop:enable Metrics/LineLength + # rubocop:enable Layout/LineLength result = double('result') result.stub(:status).and_return(255) diff --git a/spec/overcommit/hook/pre_commit/phpcs_spec.rb b/spec/overcommit/hook/pre_commit/phpcs_spec.rb index 3df6cfb5..6982a297 100644 --- a/spec/overcommit/hook/pre_commit/phpcs_spec.rb +++ b/spec/overcommit/hook/pre_commit/phpcs_spec.rb @@ -39,12 +39,12 @@ context 'and it reports a warning' do before do - # rubocop:disable Metrics/LineLength + # rubocop:disable Layout/LineLength sample_output = [ 'File,Line,Column,Type,Message,Source,Severity,Fixable', '"/Users/craig/HelpScout/overcommit-testing/invalid.php",5,1,warning,"Possible parse error: FOREACH has no AS statement",Squiz.ControlStructures.ForEachLoopDeclaration.MissingAs,5,0' ].join("\n") - # rubocop:enable Metrics/LineLength + # rubocop:enable Layout/LineLength result.stub(:stdout).and_return(sample_output) end @@ -53,12 +53,12 @@ context 'and it reports an error' do before do - # rubocop:disable Metrics/LineLength + # rubocop:disable Layout/LineLength sample_output = [ 'File,Line,Column,Type,Message,Source,Severity,Fixable', '"/Users/craig/HelpScout/overcommit-testing/invalid.php",5,1,error,"Inline control structures are not allowed",Generic.ControlStructures.InlineControlStructure.NotAllowed,5,1' ].join("\n") - # rubocop:enable Metrics/LineLength + # rubocop:enable Layout/LineLength result.stub(:stdout).and_return(sample_output) end diff --git a/spec/overcommit/utils_spec.rb b/spec/overcommit/utils_spec.rb index 3be592ff..6bf75923 100644 --- a/spec/overcommit/utils_spec.rb +++ b/spec/overcommit/utils_spec.rb @@ -119,17 +119,17 @@ describe '.supported_hook_types' do subject { described_class.supported_hook_types } - # rubocop:disable Metrics/LineLength + # rubocop:disable Layout/LineLength it { should =~ %w[commit-msg pre-commit post-checkout post-commit post-merge post-rewrite pre-push pre-rebase prepare-commit-msg] } - # rubocop:enable Metrics/LineLength + # rubocop:enable Layout/LineLength end describe '.supported_hook_type_classes' do subject { described_class.supported_hook_type_classes } - # rubocop:disable Metrics/LineLength + # rubocop:disable Layout/LineLength it { should =~ %w[CommitMsg PreCommit PostCheckout PostCommit PostMerge PostRewrite PrePush PreRebase PrepareCommitMsg] } - # rubocop:enable Metrics/LineLength + # rubocop:enable Layout/LineLength end describe '.parent_command' do @@ -190,7 +190,7 @@ it 'invokes CommandSplitter.execute' do Overcommit::CommandSplitter. should_receive(:execute). - with(arguments, args: splittable_args). + with(arguments, { args: splittable_args }). and_return(double(status: 0, stdout: '', stderr: '')) subject end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index fe6f82da..89d30fbe 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,13 +1,22 @@ # frozen_string_literal: true -if ENV['TRAVIS'] - # When running in Travis, report coverage stats to Coveralls. - require 'coveralls' - Coveralls.wear! -else - # Otherwise render coverage information in coverage/index.html and display - # coverage percentage in the console. - require 'simplecov' +require 'simplecov' +SimpleCov.start do + add_filter 'bin/' + add_filter 'libexec/' + add_filter 'spec/' + add_filter 'template-dir/' + + if ENV['CI'] + require 'simplecov-lcov' + + SimpleCov::Formatter::LcovFormatter.config do |c| + c.report_with_single_file = true + c.single_report_path = 'coverage/lcov.info' + end + + formatter SimpleCov::Formatter::LcovFormatter + end end require 'overcommit' diff --git a/template-dir/hooks/commit-msg b/template-dir/hooks/commit-msg index 197dc198..7f8023de 100755 --- a/template-dir/hooks/commit-msg +++ b/template-dir/hooks/commit-msg @@ -29,7 +29,14 @@ end # Check if Overcommit should invoke a Bundler context for loading gems require 'yaml' # rubocop:disable Style/RescueModifier -if gemfile = YAML.load_file('.overcommit.yml')['gemfile'] rescue nil +gemfile = + begin + YAML.load_file('.overcommit.yml', aliases: true)['gemfile'] + rescue ArgumentError + YAML.load_file('.overcommit.yml')['gemfile'] + end rescue nil + +if gemfile ENV['BUNDLE_GEMFILE'] = gemfile require 'bundler' diff --git a/template-dir/hooks/overcommit-hook b/template-dir/hooks/overcommit-hook index 197dc198..7f8023de 100755 --- a/template-dir/hooks/overcommit-hook +++ b/template-dir/hooks/overcommit-hook @@ -29,7 +29,14 @@ end # Check if Overcommit should invoke a Bundler context for loading gems require 'yaml' # rubocop:disable Style/RescueModifier -if gemfile = YAML.load_file('.overcommit.yml')['gemfile'] rescue nil +gemfile = + begin + YAML.load_file('.overcommit.yml', aliases: true)['gemfile'] + rescue ArgumentError + YAML.load_file('.overcommit.yml')['gemfile'] + end rescue nil + +if gemfile ENV['BUNDLE_GEMFILE'] = gemfile require 'bundler' diff --git a/template-dir/hooks/post-checkout b/template-dir/hooks/post-checkout index 197dc198..7f8023de 100755 --- a/template-dir/hooks/post-checkout +++ b/template-dir/hooks/post-checkout @@ -29,7 +29,14 @@ end # Check if Overcommit should invoke a Bundler context for loading gems require 'yaml' # rubocop:disable Style/RescueModifier -if gemfile = YAML.load_file('.overcommit.yml')['gemfile'] rescue nil +gemfile = + begin + YAML.load_file('.overcommit.yml', aliases: true)['gemfile'] + rescue ArgumentError + YAML.load_file('.overcommit.yml')['gemfile'] + end rescue nil + +if gemfile ENV['BUNDLE_GEMFILE'] = gemfile require 'bundler' diff --git a/template-dir/hooks/post-commit b/template-dir/hooks/post-commit index 197dc198..7f8023de 100755 --- a/template-dir/hooks/post-commit +++ b/template-dir/hooks/post-commit @@ -29,7 +29,14 @@ end # Check if Overcommit should invoke a Bundler context for loading gems require 'yaml' # rubocop:disable Style/RescueModifier -if gemfile = YAML.load_file('.overcommit.yml')['gemfile'] rescue nil +gemfile = + begin + YAML.load_file('.overcommit.yml', aliases: true)['gemfile'] + rescue ArgumentError + YAML.load_file('.overcommit.yml')['gemfile'] + end rescue nil + +if gemfile ENV['BUNDLE_GEMFILE'] = gemfile require 'bundler' diff --git a/template-dir/hooks/post-merge b/template-dir/hooks/post-merge index 197dc198..7f8023de 100755 --- a/template-dir/hooks/post-merge +++ b/template-dir/hooks/post-merge @@ -29,7 +29,14 @@ end # Check if Overcommit should invoke a Bundler context for loading gems require 'yaml' # rubocop:disable Style/RescueModifier -if gemfile = YAML.load_file('.overcommit.yml')['gemfile'] rescue nil +gemfile = + begin + YAML.load_file('.overcommit.yml', aliases: true)['gemfile'] + rescue ArgumentError + YAML.load_file('.overcommit.yml')['gemfile'] + end rescue nil + +if gemfile ENV['BUNDLE_GEMFILE'] = gemfile require 'bundler' diff --git a/template-dir/hooks/post-rewrite b/template-dir/hooks/post-rewrite index 197dc198..7f8023de 100755 --- a/template-dir/hooks/post-rewrite +++ b/template-dir/hooks/post-rewrite @@ -29,7 +29,14 @@ end # Check if Overcommit should invoke a Bundler context for loading gems require 'yaml' # rubocop:disable Style/RescueModifier -if gemfile = YAML.load_file('.overcommit.yml')['gemfile'] rescue nil +gemfile = + begin + YAML.load_file('.overcommit.yml', aliases: true)['gemfile'] + rescue ArgumentError + YAML.load_file('.overcommit.yml')['gemfile'] + end rescue nil + +if gemfile ENV['BUNDLE_GEMFILE'] = gemfile require 'bundler' diff --git a/template-dir/hooks/pre-commit b/template-dir/hooks/pre-commit index 197dc198..7f8023de 100755 --- a/template-dir/hooks/pre-commit +++ b/template-dir/hooks/pre-commit @@ -29,7 +29,14 @@ end # Check if Overcommit should invoke a Bundler context for loading gems require 'yaml' # rubocop:disable Style/RescueModifier -if gemfile = YAML.load_file('.overcommit.yml')['gemfile'] rescue nil +gemfile = + begin + YAML.load_file('.overcommit.yml', aliases: true)['gemfile'] + rescue ArgumentError + YAML.load_file('.overcommit.yml')['gemfile'] + end rescue nil + +if gemfile ENV['BUNDLE_GEMFILE'] = gemfile require 'bundler' diff --git a/template-dir/hooks/pre-push b/template-dir/hooks/pre-push index 197dc198..7f8023de 100755 --- a/template-dir/hooks/pre-push +++ b/template-dir/hooks/pre-push @@ -29,7 +29,14 @@ end # Check if Overcommit should invoke a Bundler context for loading gems require 'yaml' # rubocop:disable Style/RescueModifier -if gemfile = YAML.load_file('.overcommit.yml')['gemfile'] rescue nil +gemfile = + begin + YAML.load_file('.overcommit.yml', aliases: true)['gemfile'] + rescue ArgumentError + YAML.load_file('.overcommit.yml')['gemfile'] + end rescue nil + +if gemfile ENV['BUNDLE_GEMFILE'] = gemfile require 'bundler' diff --git a/template-dir/hooks/pre-rebase b/template-dir/hooks/pre-rebase index 197dc198..7f8023de 100755 --- a/template-dir/hooks/pre-rebase +++ b/template-dir/hooks/pre-rebase @@ -29,7 +29,14 @@ end # Check if Overcommit should invoke a Bundler context for loading gems require 'yaml' # rubocop:disable Style/RescueModifier -if gemfile = YAML.load_file('.overcommit.yml')['gemfile'] rescue nil +gemfile = + begin + YAML.load_file('.overcommit.yml', aliases: true)['gemfile'] + rescue ArgumentError + YAML.load_file('.overcommit.yml')['gemfile'] + end rescue nil + +if gemfile ENV['BUNDLE_GEMFILE'] = gemfile require 'bundler' diff --git a/template-dir/hooks/prepare-commit-msg b/template-dir/hooks/prepare-commit-msg index 197dc198..7f8023de 100755 --- a/template-dir/hooks/prepare-commit-msg +++ b/template-dir/hooks/prepare-commit-msg @@ -29,7 +29,14 @@ end # Check if Overcommit should invoke a Bundler context for loading gems require 'yaml' # rubocop:disable Style/RescueModifier -if gemfile = YAML.load_file('.overcommit.yml')['gemfile'] rescue nil +gemfile = + begin + YAML.load_file('.overcommit.yml', aliases: true)['gemfile'] + rescue ArgumentError + YAML.load_file('.overcommit.yml')['gemfile'] + end rescue nil + +if gemfile ENV['BUNDLE_GEMFILE'] = gemfile require 'bundler' From 33d4ae7c89a8d5597143a5666c126bd8a9b2880a Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Fri, 25 Feb 2022 22:37:08 -0800 Subject: [PATCH 03/53] Fix `YamlSyntax` to specify `aliases` option (#772) --- lib/overcommit/hook/pre_commit/yaml_syntax.rb | 10 +++++++--- spec/overcommit/hook/pre_commit/yaml_syntax_spec.rb | 1 + 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/overcommit/hook/pre_commit/yaml_syntax.rb b/lib/overcommit/hook/pre_commit/yaml_syntax.rb index fa0c4e66..493e9c5a 100644 --- a/lib/overcommit/hook/pre_commit/yaml_syntax.rb +++ b/lib/overcommit/hook/pre_commit/yaml_syntax.rb @@ -8,9 +8,13 @@ def run applicable_files.each do |file| begin - YAML.load_file(file) - rescue ArgumentError, Psych::SyntaxError => e - messages << Overcommit::Hook::Message.new(:error, file, nil, e.message) + YAML.load_file(file, aliases: true) + rescue ArgumentError + begin + YAML.load_file(file) + rescue ArgumentError, Psych::SyntaxError => e + messages << Overcommit::Hook::Message.new(:error, file, nil, e.message) + end end end diff --git a/spec/overcommit/hook/pre_commit/yaml_syntax_spec.rb b/spec/overcommit/hook/pre_commit/yaml_syntax_spec.rb index 29cb7b02..a6f61f2c 100644 --- a/spec/overcommit/hook/pre_commit/yaml_syntax_spec.rb +++ b/spec/overcommit/hook/pre_commit/yaml_syntax_spec.rb @@ -22,6 +22,7 @@ context 'when YAML file has errors' do before do + YAML.stub(:load_file).with(staged_file, { aliases: true }).and_raise(ArgumentError) YAML.stub(:load_file).with(staged_file).and_raise(ArgumentError) end From c9f78d3fca71152ecb587a2fbbabaa03eb3eac3d Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Sat, 26 Feb 2022 20:50:31 -0800 Subject: [PATCH 04/53] Fix Windows builds (#773) --- .github/workflows/tests.yml | 10 +++++++++- lib/overcommit/subprocess.rb | 5 +++++ spec/overcommit/utils_spec.rb | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e57f5204..848db60c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -7,10 +7,11 @@ on: jobs: rspec: - timeout-minutes: 10 + timeout-minutes: 15 runs-on: ${{ matrix.os }}-latest strategy: + fail-fast: false matrix: ruby-version: - '2.6' @@ -19,6 +20,13 @@ jobs: - '3.1' os: - ubuntu + - windows + + # Tempfile behavior has changed on Ruby 3.1 such that tests + # fail with permission denied. Would welcome a PR with a fix. + exclude: + - ruby-version: '3.1' + os: windows steps: - uses: actions/checkout@v2 diff --git a/lib/overcommit/subprocess.rb b/lib/overcommit/subprocess.rb index 3be06388..5899274f 100644 --- a/lib/overcommit/subprocess.rb +++ b/lib/overcommit/subprocess.rb @@ -2,6 +2,7 @@ require 'childprocess' require 'tempfile' +require 'overcommit/os' module Overcommit # Manages execution of a child process, collecting the exit status and @@ -91,6 +92,10 @@ def win32_prepare_args(args) # @param process [String] # @return [String] def to_utf8(string) + # Our encoding code doesn't work on the GitHub Actions Windows + # environment for unknown reasons, so just skip it in CI. + return string if OS.windows? && ENV['GITHUB_ACTIONS'] + if Encoding.locale_charmap == 'UTF-8' return string end diff --git a/spec/overcommit/utils_spec.rb b/spec/overcommit/utils_spec.rb index 6bf75923..acaf3eba 100644 --- a/spec/overcommit/utils_spec.rb +++ b/spec/overcommit/utils_spec.rb @@ -215,7 +215,7 @@ end it 'executes the command' do - wait_until { subject.exited? } # Make sure process terminated before checking + wait_until(timeout: 5) { subject.exited? } # Make sure process terminated before checking File.exist?('some-file').should == true end end From 736299665d9ad70d104281420f1cddaa29645e7f Mon Sep 17 00:00:00 2001 From: R Gibim <9031589+Drowze@users.noreply.github.com> Date: Thu, 28 Apr 2022 16:50:30 +0100 Subject: [PATCH 05/53] Fix pronto hooks swallowing generic errors (#779) --- lib/overcommit/hook/shared/pronto.rb | 10 +++++++++- spec/overcommit/hook/pre_commit/pronto_spec.rb | 13 +++++++++++++ spec/overcommit/hook/pre_push/pronto_spec.rb | 13 +++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/lib/overcommit/hook/shared/pronto.rb b/lib/overcommit/hook/shared/pronto.rb index 9975fbc6..cf8a3139 100644 --- a/lib/overcommit/hook/shared/pronto.rb +++ b/lib/overcommit/hook/shared/pronto.rb @@ -15,11 +15,19 @@ def run result = execute(command) return :pass if result.success? - extract_messages( + # e.g. runtime errors + generic_errors = extract_messages( + result.stderr.split("\n"), + /^(?[a-z]+)/i + ) + + pronto_infractions = extract_messages( result.stdout.split("\n").select { |line| line.match?(MESSAGE_REGEX) }, MESSAGE_REGEX, MESSAGE_TYPE_CATEGORIZER, ) + + generic_errors + pronto_infractions end end end diff --git a/spec/overcommit/hook/pre_commit/pronto_spec.rb b/spec/overcommit/hook/pre_commit/pronto_spec.rb index 7a050d10..c9d56abe 100644 --- a/spec/overcommit/hook/pre_commit/pronto_spec.rb +++ b/spec/overcommit/hook/pre_commit/pronto_spec.rb @@ -31,6 +31,7 @@ context 'and it reports an error' do before do + result.stub(:stderr).and_return('') result.stub(:stdout).and_return([ 'file2.rb:10 E: IDENTICAL code found in :iter.', ].join("\n")) @@ -41,6 +42,7 @@ context 'and it reports a warning' do before do + result.stub(:stderr).and_return('') result.stub(:stdout).and_return <<~MESSAGE Running Pronto::Rubocop file1.rb:12 W: Line is too long. [107/80] @@ -54,5 +56,16 @@ it { should warn } end + + context 'and it has a generic error message written to stderr' do + before do + result.stub(:stdout).and_return('') + result.stub(:stderr).and_return([ + 'Could not find pronto in any of the sources' + ].join("\n")) + end + + it { should fail_hook } + end end end diff --git a/spec/overcommit/hook/pre_push/pronto_spec.rb b/spec/overcommit/hook/pre_push/pronto_spec.rb index 3ca660e5..5f48b7d7 100644 --- a/spec/overcommit/hook/pre_push/pronto_spec.rb +++ b/spec/overcommit/hook/pre_push/pronto_spec.rb @@ -31,6 +31,7 @@ context 'and it reports an error' do before do + result.stub(:stderr).and_return('') result.stub(:stdout).and_return([ 'file2.rb:10 E: IDENTICAL code found in :iter.', ].join("\n")) @@ -41,6 +42,7 @@ context 'and it reports a warning' do before do + result.stub(:stderr).and_return('') result.stub(:stdout).and_return <<~MESSAGE Running Pronto::Rubocop file1.rb:12 W: Line is too long. [107/80] @@ -54,5 +56,16 @@ it { should warn } end + + context 'and it has a generic error message written to stderr' do + before do + result.stub(:stdout).and_return('') + result.stub(:stderr).and_return([ + 'Could not find pronto in any of the sources' + ].join("\n")) + end + + it { should fail_hook } + end end end From f9ecdcb909ad9df49ab28eb1aa0b5277b3ff08eb Mon Sep 17 00:00:00 2001 From: Rick Mark Date: Thu, 28 Apr 2022 10:14:30 -0700 Subject: [PATCH 06/53] Partial log flushing to make long hooks intuitive (#777) * Update specs to work when global config is using `main` for initial branch * Support flushing logs to allow long scripts to become obvious --- lib/overcommit/logger.rb | 5 +++++ lib/overcommit/printer.rb | 7 +++---- spec/spec_helper.rb | 1 + spec/support/git_spec_helpers.rb | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/overcommit/logger.rb b/lib/overcommit/logger.rb index a9ff793c..9f5d4248 100644 --- a/lib/overcommit/logger.rb +++ b/lib/overcommit/logger.rb @@ -31,6 +31,11 @@ def newline log end + # Flushes the [IO] object for partial lines + def flush + @out.flush if @out.respond_to? :flush + end + # Write a line of output. # # A newline character will always be appended. diff --git a/lib/overcommit/printer.rb b/lib/overcommit/printer.rb index 02d0995d..fcb69653 100644 --- a/lib/overcommit/printer.rb +++ b/lib/overcommit/printer.rb @@ -43,16 +43,14 @@ def end_hook(hook, status, output) end def interrupt_triggered - log.newline - log.error 'Interrupt signal received. Stopping hooks...' + log.error "\nInterrupt signal received. Stopping hooks..." end # Executed when a hook run was interrupted/cancelled by user. def run_interrupted log.newline log.warning '⚠ Hook run interrupted by user' - log.warning '⚠ If files appear modified/missing, check your stash to recover them' - log.newline + log.warning "⚠ If files appear modified/missing, check your stash to recover them\n" end # Executed when one or more hooks by the end of the run. @@ -91,6 +89,7 @@ def print_header(hook) log.partial hook.description log.partial '.' * [70 - hook.description.length - hook_name.length, 0].max log.partial hook_name + log.flush end def print_result(hook, status, output) # rubocop:disable Metrics/CyclomaticComplexity diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 89d30fbe..b6a24d82 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +require 'bundler' require 'simplecov' SimpleCov.start do add_filter 'bin/' diff --git a/spec/support/git_spec_helpers.rb b/spec/support/git_spec_helpers.rb index 23e46c51..28eb94da 100644 --- a/spec/support/git_spec_helpers.rb +++ b/spec/support/git_spec_helpers.rb @@ -13,7 +13,7 @@ module GitSpecHelpers # @return [String] path of the repository def repo(options = {}) directory('some-repo') do - create_cmd = %w[git init] + create_cmd = %w[git init --initial-branch=master] create_cmd += ['--template', options[:template_dir]] if options[:template_dir] create_cmd += ['--separate-git-dir', options[:git_dir]] if options[:git_dir] From 274e8d61a2c71615c820c0bb80b2977e2cf3c4d6 Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Thu, 28 Apr 2022 14:00:34 -0400 Subject: [PATCH 07/53] Cut version 0.59.0 (#780) Includes a disablement of one of the Windows tests on Ruby 3.0 --- CHANGELOG.md | 10 +++++++++- lib/overcommit/version.rb | 2 +- spec/integration/parallelize_spec.rb | 12 +++++++++--- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f27e6208..86a5d38b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,16 @@ # Overcommit Changelog -## master (unreleased) +## 0.59.0 * Add `--disable-pending-cops` as default flag to `RuboCop` pre-commit hook to ignore non-existent cops. Requires RuboCop `0.82.0` or newer. +* Fix deprecation warning for `Bundler.with_clean_env`. +* Fix handling of some kinds of pronto errors in the `Pronto` hook. +* Fix encoding of process output on Windows. +* Add support for specifying hook type to `--run` flag. +* Fix message regex parser for Stylelint. +* Fix configuration loading on Ruby 3.1. +* Fix `YamlSyntax` to support aliases when parsing. +* Fix run output to explicitly flush partial logs. ## 0.58.0 diff --git a/lib/overcommit/version.rb b/lib/overcommit/version.rb index ec9b0cca..8b90a4dc 100644 --- a/lib/overcommit/version.rb +++ b/lib/overcommit/version.rb @@ -2,5 +2,5 @@ # Defines the gem version. module Overcommit - VERSION = '0.58.0' + VERSION = '0.59.0' end diff --git a/spec/integration/parallelize_spec.rb b/spec/integration/parallelize_spec.rb index 20a86be3..471aa7b3 100644 --- a/spec/integration/parallelize_spec.rb +++ b/spec/integration/parallelize_spec.rb @@ -27,8 +27,14 @@ end end - it 'does not hang' do - result = Timeout.timeout(5) { subject } - result.stderr.should_not include 'No live threads left. Deadlock?' + # Test fails on Ruby 3.0 on Windows but nothing else. Would glady accept a pull + # request that resolves. + unless Overcommit::OS.windows? && + Overcommit::Utils::Version.new(RUBY_VERSION) >= '3' && + Overcommit::Utils::Version.new(RUBY_VERSION) < '3.1' + it 'does not hang' do + result = Timeout.timeout(5) { subject } + result.stderr.should_not include 'No live threads left. Deadlock?' + end end end From 1f7e5a2439a8861ccf1a9e171f68f0e7b77e0837 Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Tue, 3 May 2022 09:21:58 -0400 Subject: [PATCH 08/53] Revert `Fix encoding of process output under windows` (#784) This appears to break usage under Linux. Until a proper solution can be implemented, revert. --- lib/overcommit/subprocess.rb | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/lib/overcommit/subprocess.rb b/lib/overcommit/subprocess.rb index 5899274f..41175fb9 100644 --- a/lib/overcommit/subprocess.rb +++ b/lib/overcommit/subprocess.rb @@ -52,7 +52,7 @@ def spawn(args, options = {}) err.rewind out.rewind - Result.new(process.exit_code, to_utf8(out.read), to_utf8(err.read)) + Result.new(process.exit_code, out.read, err.read) end # Spawns a new process in the background using the given array of @@ -84,27 +84,6 @@ def win32_prepare_args(args) %w[cmd.exe /c] + [args.join(' ')] end - # Convert string from current locale to utf-8 - # - # When running commands under windows the command output is using - # current system locale (depends on system lanuage) not UTF-8 - # - # @param process [String] - # @return [String] - def to_utf8(string) - # Our encoding code doesn't work on the GitHub Actions Windows - # environment for unknown reasons, so just skip it in CI. - return string if OS.windows? && ENV['GITHUB_ACTIONS'] - - if Encoding.locale_charmap == 'UTF-8' - return string - end - - ec = Encoding::Converter.new(Encoding.locale_charmap, 'UTF-8') - # Convert encoding, alternatively simple: string.scrub will suffice - ec.convert(string) - end - # @param process [ChildProcess] # @return [Array] def assign_output_streams(process) From f777eb339aaed0f60095d634d0da1bf18d18c9e8 Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Tue, 3 May 2022 09:48:27 -0400 Subject: [PATCH 09/53] Revert addition of `--disable-pending-cops` flag to RuboCop (#783) It seems like this breaks some other workflows. Prefer the user specifying this themselves if they want it. --- config/default.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/default.yml b/config/default.yml index 51189348..bfd91e08 100644 --- a/config/default.yml +++ b/config/default.yml @@ -703,7 +703,7 @@ PreCommit: enabled: false description: 'Analyze with RuboCop' required_executable: 'rubocop' - flags: ['--format=emacs', '--force-exclusion', '--display-cop-names', '--disable-pending-cops'] + flags: ['--format=emacs', '--force-exclusion', '--display-cop-names'] install_command: 'gem install rubocop' include: - '**/*.gemspec' From a2ab659e03d3c4cd10a3cd3ac9691cc3396d041b Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Tue, 3 May 2022 09:53:15 -0400 Subject: [PATCH 10/53] Cut version 0.59.1 (#785) --- CHANGELOG.md | 5 +++++ lib/overcommit/version.rb | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86a5d38b..aa326ff2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Overcommit Changelog +## 0.59.1 + +* Remove `--disable-pending-cops` as default flag to `RuboCop` pre-commit hook. +* Remove special handling of process output on Windows since it broke on Linux. + ## 0.59.0 * Add `--disable-pending-cops` as default flag to `RuboCop` pre-commit hook to ignore non-existent cops. Requires RuboCop `0.82.0` or newer. diff --git a/lib/overcommit/version.rb b/lib/overcommit/version.rb index 8b90a4dc..e8f6bb39 100644 --- a/lib/overcommit/version.rb +++ b/lib/overcommit/version.rb @@ -2,5 +2,5 @@ # Defines the gem version. module Overcommit - VERSION = '0.59.0' + VERSION = '0.59.1' end From 8812c5f0560da43e1fa2c613684ea9b628945628 Mon Sep 17 00:00:00 2001 From: Carlos Palhares Date: Sun, 11 Sep 2022 07:21:16 -0300 Subject: [PATCH 11/53] Allow overriding Gemfile.lock (#796) * Allow overriding Gemfile.lock * Fix lint rule violation --- lib/overcommit/hook/pre_commit/bundle_check.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/overcommit/hook/pre_commit/bundle_check.rb b/lib/overcommit/hook/pre_commit/bundle_check.rb index 10d30d2c..70f5fa2e 100644 --- a/lib/overcommit/hook/pre_commit/bundle_check.rb +++ b/lib/overcommit/hook/pre_commit/bundle_check.rb @@ -6,7 +6,7 @@ module Overcommit::Hook::PreCommit # # @see http://bundler.io/ class BundleCheck < Base - LOCK_FILE = 'Gemfile.lock' + LOCK_FILE = File.basename(ENV['BUNDLE_GEMFILE'] || 'Gemfile') + '.lock' def run # Ignore if Gemfile.lock is not tracked by git From 1e62370e8b29a96961c3f9c4e17d936dbcb05e19 Mon Sep 17 00:00:00 2001 From: Mark Delk Date: Sun, 18 Dec 2022 17:00:33 -0600 Subject: [PATCH 12/53] support trailing space in replace_branch's 'replacement_text' config (#804) --- lib/overcommit/hook/prepare_commit_msg/replace_branch.rb | 8 ++++---- .../hook/prepare_commit_msg/replace_branch_spec.rb | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/overcommit/hook/prepare_commit_msg/replace_branch.rb b/lib/overcommit/hook/prepare_commit_msg/replace_branch.rb index 7a40ed69..e8c09887 100644 --- a/lib/overcommit/hook/prepare_commit_msg/replace_branch.rb +++ b/lib/overcommit/hook/prepare_commit_msg/replace_branch.rb @@ -11,9 +11,9 @@ module Overcommit::Hook::PrepareCommitMsg # For instance, if your current branch is `123-topic` then this config # # branch_pattern: '(\d+)-(\w+)' - # replacement_text: '[#\1]' + # replacement_text: '[#\1] ' # - # would make this hook prepend commit messages with `[#123]`. + # would make this hook prepend commit messages with `[#123] `. # # Similarly, a replacement text of `[\1][\2]` would result in `[123][topic]`. # @@ -53,7 +53,7 @@ def new_template @new_template ||= begin curr_branch = Overcommit::GitRepo.current_branch - curr_branch.gsub(branch_pattern, replacement_text).strip + curr_branch.gsub(branch_pattern, replacement_text) end end @@ -69,7 +69,7 @@ def replacement_text @replacement_text ||= begin if File.exist?(replacement_text_config) - File.read(replacement_text_config) + File.read(replacement_text_config).chomp else replacement_text_config end diff --git a/spec/overcommit/hook/prepare_commit_msg/replace_branch_spec.rb b/spec/overcommit/hook/prepare_commit_msg/replace_branch_spec.rb index 3844f77a..6af27921 100644 --- a/spec/overcommit/hook/prepare_commit_msg/replace_branch_spec.rb +++ b/spec/overcommit/hook/prepare_commit_msg/replace_branch_spec.rb @@ -62,6 +62,14 @@ def remove_file(name) it 'prepends the replacement text' do expect(File.read('COMMIT_EDITMSG')).to eq("[#123]\n") end + + context 'when the replacement text contains a space' do + let(:config) { new_config('replacement_text' => '[\1] ') } + + it 'prepends the replacement text, including the space' do + expect(File.read('COMMIT_EDITMSG')).to eq("[123] \n") + end + end end context "when the checked out branch doesn't matches the pattern" do From 9aa62593f56c2f5f09d411214f482252c9a300a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Kova=C4=8D?= Date: Mon, 19 Dec 2022 00:01:18 +0100 Subject: [PATCH 13/53] Add MixFormat hook (#801) --- config/default.yml | 10 ++++ lib/overcommit/hook/pre_commit/mix_format.rb | 30 ++++++++++++ .../hook/pre_commit/mix_format_spec.rb | 47 +++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 lib/overcommit/hook/pre_commit/mix_format.rb create mode 100644 spec/overcommit/hook/pre_commit/mix_format_spec.rb diff --git a/config/default.yml b/config/default.yml index bfd91e08..42ea17a8 100644 --- a/config/default.yml +++ b/config/default.yml @@ -536,6 +536,16 @@ PreCommit: required_executable: 'grep' flags: ['-IHn', "^<<<<<<<[ \t]"] + MixFormat: + enabled: false + description: 'Check formatting with mix format' + required_executable: 'mix' + flags: ['format', '--check-formatted'] + include: + - '**/*.ex' + - '**/*.heex' + - '**/*.exs' + PuppetMetadataJsonLint: enabled: false description: 'Checking module metadata' diff --git a/lib/overcommit/hook/pre_commit/mix_format.rb b/lib/overcommit/hook/pre_commit/mix_format.rb new file mode 100644 index 00000000..2fa07551 --- /dev/null +++ b/lib/overcommit/hook/pre_commit/mix_format.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +module Overcommit::Hook::PreCommit + # Runs `mix format --check-formatted` against any modified ex/heex/exs files. + # + # @see https://hexdocs.pm/mix/main/Mix.Tasks.Format.html + class MixFormat < Base + # example message: + # ** (Mix) mix format failed due to --check-formatted. + # The following files are not formatted: + # + # * lib/file1.ex + # * lib/file2.ex + FILES_REGEX = /^\s+\*\s+(?.+)$/.freeze + + def run + result = execute(command, args: applicable_files) + return :pass if result.success? + + result.stderr.scan(FILES_REGEX).flatten. + map { |file| message(file) } + end + + private + + def message(file) + Overcommit::Hook::Message.new(:error, file, nil, file) + end + end +end diff --git a/spec/overcommit/hook/pre_commit/mix_format_spec.rb b/spec/overcommit/hook/pre_commit/mix_format_spec.rb new file mode 100644 index 00000000..9acc50ed --- /dev/null +++ b/spec/overcommit/hook/pre_commit/mix_format_spec.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Overcommit::Hook::PreCommit::MixFormat do + let(:config) { Overcommit::ConfigurationLoader.default_configuration } + let(:context) { double('context') } + subject { described_class.new(config, context) } + + before do + subject.stub(:applicable_files).and_return(%w[file1.ex file2.exs]) + end + + context 'when mix format exits successfully' do + before do + result = double('result') + result.stub(:success?).and_return(true) + subject.stub(:execute).and_return(result) + end + + it { should pass } + end + + context 'when mix format exits unsucessfully' do + let(:result) { double('result') } + + before do + result.stub(:success?).and_return(false) + subject.stub(:execute).and_return(result) + end + + context 'and it reports an error' do + before do + result.stub(:stdout).and_return('') + result.stub(:stderr).and_return([ + '** (Mix) mix format failed due to --check-formatted.', + 'The following files are not formatted:', + '', + ' * lib/file1.ex', + ' * lib/file2.ex' + ].join("\n")) + end + + it { should fail_hook } + end + end +end From 774019a0b60c138ea229facf6e0fcaabf0336d5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Kova=C4=8D?= Date: Mon, 19 Dec 2022 00:01:34 +0100 Subject: [PATCH 14/53] Add MixTest hook (#802) --- config/default.yml | 6 ++++ lib/overcommit/hook/pre_push/mix_test.rb | 16 ++++++++++ .../overcommit/hook/pre_push/mix_test_spec.rb | 31 +++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 lib/overcommit/hook/pre_push/mix_test.rb create mode 100644 spec/overcommit/hook/pre_push/mix_test_spec.rb diff --git a/config/default.yml b/config/default.yml index 42ea17a8..181187af 100644 --- a/config/default.yml +++ b/config/default.yml @@ -1326,6 +1326,12 @@ PrePush: command: ['ruby', '-Ilib:test', '-rminitest', "-e 'exit! Minitest.run'"] include: 'test/**/*_test.rb' + MixTest: + enabled: false + description: 'Run mix test suite' + required_executable: 'mix' + flags: ['test'] + PhpUnit: enabled: false description: 'Run PhpUnit test suite' diff --git a/lib/overcommit/hook/pre_push/mix_test.rb b/lib/overcommit/hook/pre_push/mix_test.rb new file mode 100644 index 00000000..3ce005e9 --- /dev/null +++ b/lib/overcommit/hook/pre_push/mix_test.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module Overcommit::Hook::PrePush + # Runs `mix test` test suite before push + # + # @see https://hexdocs.pm/mix/Mix.Tasks.Test.html + class MixTest < Base + def run + result = execute(command) + return :pass if result.success? + + output = result.stdout + result.stderr + [:fail, output] + end + end +end diff --git a/spec/overcommit/hook/pre_push/mix_test_spec.rb b/spec/overcommit/hook/pre_push/mix_test_spec.rb new file mode 100644 index 00000000..798da7f7 --- /dev/null +++ b/spec/overcommit/hook/pre_push/mix_test_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Overcommit::Hook::PrePush::MixTest do + let(:config) { Overcommit::ConfigurationLoader.default_configuration } + let(:context) { double('context') } + subject { described_class.new(config, context) } + + context 'when mix test exits successfully' do + before do + result = double('result') + result.stub(:success?).and_return(true) + subject.stub(:execute).and_return(result) + end + + it { should pass } + end + + context 'when mix test exits unsucessfully' do + before do + result = double('result') + result.stub(:success?).and_return(false) + result.stub(:stdout).and_return('Some error message') + result.stub(:stderr).and_return('') + subject.stub(:execute).and_return(result) + end + + it { should fail_hook 'Some error message' } + end +end From 807de37897834c1083f19616860382d2c989a69c Mon Sep 17 00:00:00 2001 From: Julianna Date: Fri, 20 Jan 2023 00:40:46 -0600 Subject: [PATCH 15/53] Add optional additional local configuration (#799) Adds support for an additional configuration file, .local-overcommit.yml, in order to allow local configuration on a local box. That way the main config .overcommit.yml can be commited to a repo and a local developer can also add configurations to this new file. --- README.md | 4 ++ lib/overcommit/configuration_loader.rb | 16 ++++++-- lib/overcommit/constants.rb | 1 + spec/overcommit/configuration_loader_spec.rb | 42 ++++++++++++++++++++ 4 files changed, 59 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0464e604..afcbcbbf 100644 --- a/README.md +++ b/README.md @@ -208,6 +208,10 @@ PreCommit: command: ['bundle', 'exec', 'rubocop'] # Invoke within Bundler context ``` +Additionally, you may wish to have repo-specific configurations that are local to your computer that are not part of the shared repo config. +Adding a `.local-overcommit.yml` file in the top-level directory of the repository adds another configuration file. This file works the same as `.overcommit.yml`. +Adding this to ignored files in a git repo will allow you to have a local configuration per repo. + ### Hook Options Individual hooks expose both built-in configuration options as well as their diff --git a/lib/overcommit/configuration_loader.rb b/lib/overcommit/configuration_loader.rb index 77a08549..e4063d7e 100644 --- a/lib/overcommit/configuration_loader.rb +++ b/lib/overcommit/configuration_loader.rb @@ -53,10 +53,14 @@ def initialize(logger, options = {}) # # @return [Overcommit::Configuration] def load_repo_config + overcommit_local_yml = File.join(Overcommit::Utils.repo_root, + Overcommit::LOCAL_CONFIG_FILE_NAME) overcommit_yml = File.join(Overcommit::Utils.repo_root, Overcommit::CONFIG_FILE_NAME) - if File.exist?(overcommit_yml) + if File.exist?(overcommit_local_yml) && File.exist?(overcommit_yml) + load_file(overcommit_yml, overcommit_local_yml) + elsif File.exist?(overcommit_yml) load_file(overcommit_yml) else self.class.default_configuration @@ -64,9 +68,13 @@ def load_repo_config end # Loads a configuration, ensuring it extends the default configuration. - def load_file(file) - config = self.class.load_from_file(file, default: false, logger: @log) - config = self.class.default_configuration.merge(config) + def load_file(file, local_file = nil) + overcommit_config = self.class.load_from_file(file, default: false, logger: @log) + if local_file + local_config = self.class.load_from_file(local_file, default: false, logger: @log) + end + config = self.class.default_configuration.merge(overcommit_config) + config = self.class.default_configuration.merge(local_config) if local_config if @options.fetch(:verify) { config.verify_signatures? } verify_signatures(config) diff --git a/lib/overcommit/constants.rb b/lib/overcommit/constants.rb index dd027932..e7c19728 100644 --- a/lib/overcommit/constants.rb +++ b/lib/overcommit/constants.rb @@ -4,6 +4,7 @@ module Overcommit HOME = File.expand_path(File.join(File.dirname(__FILE__), '..', '..')).freeze CONFIG_FILE_NAME = '.overcommit.yml' + LOCAL_CONFIG_FILE_NAME = '.local-overcommit.yml' HOOK_DIRECTORY = File.join(HOME, 'lib', 'overcommit', 'hook').freeze diff --git a/spec/overcommit/configuration_loader_spec.rb b/spec/overcommit/configuration_loader_spec.rb index a99608d4..2ddbe4e6 100644 --- a/spec/overcommit/configuration_loader_spec.rb +++ b/spec/overcommit/configuration_loader_spec.rb @@ -57,5 +57,47 @@ end end end + + context 'when repo contains a local configuration file' do + let(:config_contents) { <<-CFG } + plugin_directory: 'some-directory' + CFG + + let(:local_config_contents) { <<-CFG } + plugin_directory: 'some-different-directory' + CFG + + around do |example| + repo do + File.open('.overcommit.yml', 'w') { |f| f.write(config_contents) } + File.open('.local-overcommit.yml', 'w') { |f| f.write(local_config_contents) } + example.run + end + end + + it 'loads the file' do + Overcommit::ConfigurationLoader.any_instance. + should_receive(:load_file). + with(File.expand_path('.overcommit.yml'), File.expand_path('.local-overcommit.yml')) + subject + end + + it 'merges each loaded file with the default configuration' do + subject.plugin_directory.should == File.expand_path('some-different-directory') + end + + context 'and the configuration file contains a hook with no `enabled` option' do + let(:config_contents) { <<-CFG } + PreCommit: + ScssLint: + command: ['bundle', 'exec', 'scss-lint'] + CFG + + it 'displays a warning' do + subject + output.string.should =~ /PreCommit::ScssLint.*not.*enabled/i + end + end + end end end From 4d204bdb6ed8ef001ecd0175fb9de8b658cf04cc Mon Sep 17 00:00:00 2001 From: Kevin McCormack Date: Fri, 20 Jan 2023 01:41:27 -0500 Subject: [PATCH 16/53] Rescue Psych::DisallowedClass in YamlSyntax (#805) * Rescue Psych::DisallowedClass in YamlSyntax This improves the output for errors safe loading disallowed classes with psych 5.0 * Remove extra whitespace --- lib/overcommit/hook/pre_commit/yaml_syntax.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/overcommit/hook/pre_commit/yaml_syntax.rb b/lib/overcommit/hook/pre_commit/yaml_syntax.rb index 493e9c5a..dd685450 100644 --- a/lib/overcommit/hook/pre_commit/yaml_syntax.rb +++ b/lib/overcommit/hook/pre_commit/yaml_syntax.rb @@ -15,10 +15,19 @@ def run rescue ArgumentError, Psych::SyntaxError => e messages << Overcommit::Hook::Message.new(:error, file, nil, e.message) end + rescue Psych::DisallowedClass => e + messages << error_message(file, e) end end messages end + + private + + def error_message(file, error) + text = "#{file}: #{error.message}" + Overcommit::Hook::Message.new(:error, file, nil, text) + end end end From 8bc2eec0375bf2f75b7f39453713e8dec49ae679 Mon Sep 17 00:00:00 2001 From: Thomas Millward Wright Date: Fri, 20 Jan 2023 06:45:26 +0000 Subject: [PATCH 17/53] Add non ASCII encoding schema support to RailsSchemaUpToDate hook (#786) * Add non ASCII encoding schema support to RailsSchemaUpToDate hook * Add guard to check presence of @config['encoding'] Co-authored-by: Paul Wilson --- .../pre_commit/rails_schema_up_to_date.rb | 8 +++++- .../rails_schema_up_to_date_spec.rb | 27 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb b/lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb index 13d7932f..dafd31a1 100644 --- a/lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb +++ b/lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb @@ -34,6 +34,12 @@ def run # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplex private + def encoding + return unless @config.key?('encoding') + + { encoding: @config['encoding'] }.compact + end + def migration_files @migration_files ||= applicable_files.select do |file| file.match %r{db/migrate/.*\.rb} @@ -47,7 +53,7 @@ def schema_files end def schema - @schema ||= schema_files.map { |file| File.read(file) }.join + @schema ||= schema_files.map { |file| File.read(file, encoding) }.join @schema.tr('_', '') end diff --git a/spec/overcommit/hook/pre_commit/rails_schema_up_to_date_spec.rb b/spec/overcommit/hook/pre_commit/rails_schema_up_to_date_spec.rb index ad53485e..9ee704b7 100644 --- a/spec/overcommit/hook/pre_commit/rails_schema_up_to_date_spec.rb +++ b/spec/overcommit/hook/pre_commit/rails_schema_up_to_date_spec.rb @@ -70,6 +70,33 @@ end it { should fail_hook } + + context 'when non ASCII encoding is required' do + let!(:config) do + super().merge(Overcommit::Configuration.new( + 'PreCommit' => { + 'RailsSchemaUpToDate' => { + 'encoding' => 'utf-8' + } + } + )) + end + + before do + subject.stub(:applicable_files).and_return([sql_schema_file]) + end + + around do |example| + repo do + FileUtils.mkdir_p('db/migrate') + File.open(sql_schema_file, 'w') { |f| f.write("version: 12345678901234\nVALUES ('字')") } + `git add #{sql_schema_file}` + example.run + end + end + + it { should fail_hook } + end end context 'when a Ruby schema file with the latest version and migrations are added' do From 2214dd12f5dd6cd944a5c7a6c5a4ea25e2668349 Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Thu, 19 Jan 2023 22:57:23 -0800 Subject: [PATCH 18/53] Cut version 0.60.0 (#807) --- CHANGELOG.md | 10 ++++++++++ lib/overcommit/version.rb | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa326ff2..ca3a52eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Overcommit Changelog +## 0.60.0 + +* Allow overriding `Gemfile.lock` location for `BundleCheck` pre-commit hook +* Fix `ReplaceBranch` prepare-commit-msg hook to allow trailing spaces +* Add `MixFormat` pre-commit hook +* Add `MixTest` pre-push hook +* Allow loading custom local configuration from `.local-overcommit.yml` +* Handle `Psych::DisallowedClass` when running `YamlSyntax` pre-commit hook +* Add support for specifying custom `encoding` in `RailsSchemaUpToDate` pre-commit hook + ## 0.59.1 * Remove `--disable-pending-cops` as default flag to `RuboCop` pre-commit hook. diff --git a/lib/overcommit/version.rb b/lib/overcommit/version.rb index e8f6bb39..0c03dd7f 100644 --- a/lib/overcommit/version.rb +++ b/lib/overcommit/version.rb @@ -2,5 +2,5 @@ # Defines the gem version. module Overcommit - VERSION = '0.59.1' + VERSION = '0.60.0' end From 90e367940b87e3a22a4654ed536d20db2e380256 Mon Sep 17 00:00:00 2001 From: Linus Oleander Date: Mon, 27 Mar 2023 19:28:19 +0200 Subject: [PATCH 19/53] Allow ReplaceBranch to use skip_if (#809) * Allow ReplaceBranch to use skip_if * Fix linting error * Clearify specs * Use bash instead of sh in spec --- .../hook/prepare_commit_msg/replace_branch.rb | 2 +- .../prepare_commit_msg/replace_branch_spec.rb | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/overcommit/hook/prepare_commit_msg/replace_branch.rb b/lib/overcommit/hook/prepare_commit_msg/replace_branch.rb index e8c09887..8852b0b5 100644 --- a/lib/overcommit/hook/prepare_commit_msg/replace_branch.rb +++ b/lib/overcommit/hook/prepare_commit_msg/replace_branch.rb @@ -85,7 +85,7 @@ def skipped_commit_types end def skip? - skipped_commit_types.include?(commit_message_source) + super || skipped_commit_types.include?(commit_message_source) end end end diff --git a/spec/overcommit/hook/prepare_commit_msg/replace_branch_spec.rb b/spec/overcommit/hook/prepare_commit_msg/replace_branch_spec.rb index 6af27921..e355517f 100644 --- a/spec/overcommit/hook/prepare_commit_msg/replace_branch_spec.rb +++ b/spec/overcommit/hook/prepare_commit_msg/replace_branch_spec.rb @@ -70,6 +70,26 @@ def remove_file(name) expect(File.read('COMMIT_EDITMSG')).to eq("[123] \n") end end + + context 'when skip_if exits with a zero status' do + let(:config) { new_config('skip_if' => ['bash', '-c', 'exit 0']) } + + it { is_expected.to pass } + + it 'does not change the commit message' do + expect(File.read('COMMIT_EDITMSG')).to eq("\n") + end + end + + context 'when skip_if exits with a non-zero status' do + let(:config) { new_config('skip_if' => ['bash', '-c', 'exit 1']) } + + it { is_expected.to pass } + + it 'does change the commit message' do + expect(File.read('COMMIT_EDITMSG')).to eq("[#123]\n") + end + end end context "when the checked out branch doesn't matches the pattern" do From 02f7b3ef2d455fff46cb6d5a0877a5193bc769c9 Mon Sep 17 00:00:00 2001 From: Julianna Date: Wed, 13 Dec 2023 01:05:04 -0600 Subject: [PATCH 20/53] fix: local overcommit file merges with existing .overcommit.yml file (#815) --- lib/overcommit/configuration_loader.rb | 6 +- spec/overcommit/configuration_loader_spec.rb | 62 ++++++++++++++------ 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/lib/overcommit/configuration_loader.rb b/lib/overcommit/configuration_loader.rb index e4063d7e..8fd68a01 100644 --- a/lib/overcommit/configuration_loader.rb +++ b/lib/overcommit/configuration_loader.rb @@ -70,11 +70,9 @@ def load_repo_config # Loads a configuration, ensuring it extends the default configuration. def load_file(file, local_file = nil) overcommit_config = self.class.load_from_file(file, default: false, logger: @log) - if local_file - local_config = self.class.load_from_file(local_file, default: false, logger: @log) - end + l_config = self.class.load_from_file(local_file, default: false, logger: @log) if local_file config = self.class.default_configuration.merge(overcommit_config) - config = self.class.default_configuration.merge(local_config) if local_config + config = config.merge(l_config) if l_config if @options.fetch(:verify) { config.verify_signatures? } verify_signatures(config) diff --git a/spec/overcommit/configuration_loader_spec.rb b/spec/overcommit/configuration_loader_spec.rb index 2ddbe4e6..90497201 100644 --- a/spec/overcommit/configuration_loader_spec.rb +++ b/spec/overcommit/configuration_loader_spec.rb @@ -58,11 +58,32 @@ end end - context 'when repo contains a local configuration file' do + context 'when repo only contains a repo level configuration file' do let(:config_contents) { <<-CFG } - plugin_directory: 'some-directory' + PreCommit: + Rubocop: + enabled: true CFG + around do |example| + repo do + File.open('.overcommit.yml', 'w') { |f| f.write(config_contents) } + example.run + end + end + + it 'includes default settings' do + subject + subject.for_hook('CapitalizedSubject', 'CommitMsg').should include('enabled' => true) + end + + it 'includes .overwrite.yml configs' do + subject + subject.for_hook('Rubocop', 'PreCommit').should include('enabled' => true) + end + end + + context 'when repo also contains a local configuration file' do let(:local_config_contents) { <<-CFG } plugin_directory: 'some-different-directory' CFG @@ -75,28 +96,31 @@ end end - it 'loads the file' do - Overcommit::ConfigurationLoader.any_instance. - should_receive(:load_file). - with(File.expand_path('.overcommit.yml'), File.expand_path('.local-overcommit.yml')) + let(:config_contents) { <<-CFG } + PreCommit: + ScssLint: + enabled: true + CFG + + let(:local_config_contents) { <<-CFG } + PreCommit: + Rubocop: + enabled: true + CFG + + it 'includes default settings' do subject + subject.for_hook('CapitalizedSubject', 'CommitMsg').should include('enabled' => true) end - it 'merges each loaded file with the default configuration' do - subject.plugin_directory.should == File.expand_path('some-different-directory') + it 'includes .overwrite.yml configs' do + subject + subject.for_hook('ScssLint', 'PreCommit').should include('enabled' => true) end - context 'and the configuration file contains a hook with no `enabled` option' do - let(:config_contents) { <<-CFG } - PreCommit: - ScssLint: - command: ['bundle', 'exec', 'scss-lint'] - CFG - - it 'displays a warning' do - subject - output.string.should =~ /PreCommit::ScssLint.*not.*enabled/i - end + it 'includes .local-overwrite.yml configs' do + subject + subject.for_hook('Rubocop', 'PreCommit').should include('enabled' => true) end end end From 38febfc1d798a5220d97c58307a8621e8d427258 Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Tue, 12 Dec 2023 23:09:05 -0800 Subject: [PATCH 21/53] Cut version 0.61.0 (#817) --- CHANGELOG.md | 5 +++++ lib/overcommit/version.rb | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca3a52eb..cc14f3f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Overcommit Changelog +## 0.61.0 + +* Allow `ReplaceBranch` to use `skip_if` +* Fix local Overcommit file merges with existing `.overcommit.yml` + ## 0.60.0 * Allow overriding `Gemfile.lock` location for `BundleCheck` pre-commit hook diff --git a/lib/overcommit/version.rb b/lib/overcommit/version.rb index 0c03dd7f..0646ce48 100644 --- a/lib/overcommit/version.rb +++ b/lib/overcommit/version.rb @@ -2,5 +2,5 @@ # Defines the gem version. module Overcommit - VERSION = '0.60.0' + VERSION = '0.61.0' end From 4f11048e99134ea0e4128d7ad6694f3b230d88f1 Mon Sep 17 00:00:00 2001 From: Denis Zaratan Pasin Date: Wed, 13 Dec 2023 08:11:36 +0100 Subject: [PATCH 22/53] Adding Ruby 3.2 to test matrix (#816) --- .github/workflows/tests.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 848db60c..416afe34 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -18,6 +18,7 @@ jobs: - '2.7' - '3.0' - '3.1' + - '3.2' os: - ubuntu - windows @@ -27,6 +28,8 @@ jobs: exclude: - ruby-version: '3.1' os: windows + - ruby-version: '3.2' + os: windows steps: - uses: actions/checkout@v2 From faf76fc7aa01c2b3264020ed301b569a9ed53360 Mon Sep 17 00:00:00 2001 From: Andy Waite <13400+andyw8@users.noreply.github.com> Date: Sun, 14 Jan 2024 21:06:39 -0500 Subject: [PATCH 23/53] Update RuboCop (#818) The current version of Ruby is from April 2020. Since there are quite a lot of new issues identified, I've committed them to the `.rubocop_todo.yml` so that they can be addressed incrementally or disabled. Co-authored-by: Andy Waite --- .rubocop.yml | 2 + .rubocop_todo.yml | 137 ++++++++++++++++++ Gemfile | 4 +- .../hook/pre_commit/phpcs_fixer_spec.rb | 12 +- 4 files changed, 147 insertions(+), 8 deletions(-) create mode 100644 .rubocop_todo.yml diff --git a/.rubocop.yml b/.rubocop.yml index 35002594..8c779097 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,3 +1,5 @@ +inherit_from: .rubocop_todo.yml + AllCops: TargetRubyVersion: 2.4 diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 00000000..53df9159 --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,137 @@ +# This configuration was generated by +# `rubocop --auto-gen-config --auto-gen-only-exclude --no-exclude-limit` +# on 2024-01-10 14:09:00 UTC using RuboCop version 1.59.0. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowAliasSyntax, AllowedMethods. +# AllowedMethods: alias_method, public, protected, private +Layout/EmptyLinesAroundAttributeAccessor: + Exclude: + - 'lib/overcommit/hook_context/post_merge.rb' + +# Offense count: 6 +# Configuration parameters: AllowedMethods. +# AllowedMethods: enums +Lint/ConstantDefinitionInBlock: + Exclude: + - 'spec/overcommit/message_processor_spec.rb' + +# Offense count: 4 +Lint/MixedRegexpCaptureTypes: + Exclude: + - 'lib/overcommit/hook/pre_commit/dart_analyzer.rb' + - 'lib/overcommit/hook/pre_commit/java_checkstyle.rb' + - 'lib/overcommit/hook/pre_commit/kt_lint.rb' + - 'lib/overcommit/hook/pre_commit/scalastyle.rb' + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +Lint/RedundantCopDisableDirective: + Exclude: + - 'lib/overcommit/hook_runner.rb' + - 'lib/overcommit/printer.rb' + +# Offense count: 1 +# Configuration parameters: CountComments, Max, CountAsOne. +Metrics/ClassLength: + Exclude: + - 'lib/overcommit/utils.rb' + +# Offense count: 2 +# Configuration parameters: AllowedMethods, AllowedPatterns, Max. +Metrics/CyclomaticComplexity: + Exclude: + - 'lib/overcommit/configuration.rb' + - 'lib/overcommit/hook_runner.rb' + +# Offense count: 3 +# Configuration parameters: AllowedMethods, AllowedPatterns, Max. +Metrics/PerceivedComplexity: + Exclude: + - 'lib/overcommit/configuration.rb' + - 'lib/overcommit/configuration_validator.rb' + - 'lib/overcommit/hook_runner.rb' + +# Offense count: 23 +# This cop supports unsafe autocorrection (--autocorrect-all). +Style/GlobalStdStream: + Exclude: + - 'bin/overcommit' + - 'lib/overcommit/hook/post_commit/git_guilt.rb' + - 'template-dir/hooks/commit-msg' + - 'template-dir/hooks/overcommit-hook' + - 'template-dir/hooks/post-checkout' + - 'template-dir/hooks/post-commit' + - 'template-dir/hooks/post-merge' + - 'template-dir/hooks/post-rewrite' + - 'template-dir/hooks/pre-commit' + - 'template-dir/hooks/pre-push' + - 'template-dir/hooks/pre-rebase' + - 'template-dir/hooks/prepare-commit-msg' + +# Offense count: 2 +# This cop supports unsafe autocorrection (--autocorrect-all). +Style/HashTransformValues: + Exclude: + - 'lib/overcommit/configuration.rb' + - 'lib/overcommit/configuration_validator.rb' + +# Offense count: 1 +# Configuration parameters: AllowedMethods. +# AllowedMethods: respond_to_missing? +Style/OptionalBooleanParameter: + Exclude: + - 'lib/overcommit/logger.rb' + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +Style/RedundantBegin: + Exclude: + - 'lib/overcommit/hook/prepare_commit_msg/replace_branch.rb' + - 'lib/overcommit/utils.rb' + +# Offense count: 10 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: SafeForConstants. +Style/RedundantFetchBlock: + Exclude: + - 'lib/overcommit/configuration.rb' + - 'lib/overcommit/configuration_validator.rb' + - 'lib/overcommit/hook/base.rb' + - 'lib/overcommit/hook/pre_commit/chamber_verification.rb' + - 'lib/overcommit/logger.rb' + - 'spec/support/shell_helpers.rb' + +# Offense count: 8 +# This cop supports safe autocorrection (--autocorrect). +Style/RedundantRegexpEscape: + Exclude: + - 'lib/overcommit/configuration.rb' + - 'lib/overcommit/hook/pre_commit/php_cs.rb' + - 'lib/overcommit/hook/pre_commit/php_lint.rb' + - 'lib/overcommit/hook/pre_commit/php_stan.rb' + +# Offense count: 15 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: Mode. +Style/StringConcatenation: + Exclude: + - 'lib/overcommit/hook/pre_commit/bundle_check.rb' + - 'lib/overcommit/hook_runner.rb' + - 'lib/overcommit/message_processor.rb' + - 'spec/integration/gemfile_option_spec.rb' + - 'spec/overcommit/hook/commit_msg/text_width_spec.rb' + - 'spec/overcommit/hook/prepare_commit_msg/base_spec.rb' + - 'spec/overcommit/message_processor_spec.rb' + - 'spec/spec_helper.rb' + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +Style/ZeroLengthPredicate: + Exclude: + - 'lib/overcommit/hook/pre_commit/ruby_syntax.rb' diff --git a/Gemfile b/Gemfile index ff22be0c..53b13c7f 100644 --- a/Gemfile +++ b/Gemfile @@ -11,7 +11,7 @@ gem 'rspec', '~> 3.0' gem 'simplecov', '~> 0.21.0' gem 'simplecov-lcov', '~> 0.8.0' -# Pin RuboCop for Travis builds. -gem 'rubocop', '0.82.0' +# Pin RuboCop for CI builds +gem 'rubocop', '1.59.0' gem 'ffi' if Gem.win_platform? diff --git a/spec/overcommit/hook/pre_commit/phpcs_fixer_spec.rb b/spec/overcommit/hook/pre_commit/phpcs_fixer_spec.rb index 33b0d7c1..a4b1e187 100644 --- a/spec/overcommit/hook/pre_commit/phpcs_fixer_spec.rb +++ b/spec/overcommit/hook/pre_commit/phpcs_fixer_spec.rb @@ -13,7 +13,7 @@ context 'when phpcs fixer exits successfully with fixed file' do before do - # rubocop:disable Metrics/LineLength + # rubocop:disable Layout/LineLength sample_output = [ 'Loaded config default.', 'Using cache file ".php_cs.cache".', @@ -24,7 +24,7 @@ 'Fixed all files in 0.001 seconds, 10.000 MB memory used', '', ].join("\n") - # rubocop:enable Metrics/LineLength + # rubocop:enable Layout/LineLength result = double('result') result.stub(:status).and_return(0) @@ -38,7 +38,7 @@ context 'when phpcs fixer exits successfully with no file to fix' do before do - # rubocop:disable Metrics/LineLength + # rubocop:disable Layout/LineLength sample_output = [ 'Loaded config default.', 'Using cache file ".php_cs.cache".', @@ -46,7 +46,7 @@ 'Legend: ?-unknown, I-invalid file syntax, file ignored, S-Skipped, .-no changes, F-fixed, E-error', '', ].join("\n") - # rubocop:enable Metrics/LineLength + # rubocop:enable Layout/LineLength result = double('result') result.stub(:status).and_return(0) @@ -60,7 +60,7 @@ context 'when phpcs exits unsuccessfully' do before do - # rubocop:disable Metrics/LineLength + # rubocop:disable Layout/LineLength sample_output = [ 'Loaded config default.', 'Using cache file ".php_cs.cache".', @@ -72,7 +72,7 @@ ' 1) /home/damien/Code/Rezdy/php/foo/broken.php', '', ].join("\n") - # rubocop:enable Metrics/LineLength + # rubocop:enable Layout/LineLength result = double('result') result.stub(:status).and_return(1) From bc1fec660e5c7c0cd83e2c8b3de8f02b55c0b367 Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Sun, 14 Jan 2024 18:17:08 -0800 Subject: [PATCH 24/53] Update branch for CI from `master` to `main` (#819) This was missed when we switched to using `main`. --- .github/workflows/lint.yml | 6 +++--- .github/workflows/tests.yml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b1879f09..8b23cbab 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,9 +1,9 @@ name: Lint on: push: - branches: [master] + branches: [main] pull_request: - branches: [master] + branches: [main] jobs: overcommit: @@ -16,7 +16,7 @@ jobs: - name: Set up Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: 2.7 + ruby-version: 3.3 bundler-cache: true - name: Prepare environment diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 416afe34..26c20dd1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,9 +1,9 @@ name: Tests on: push: - branches: [master] + branches: [main] pull_request: - branches: [master] + branches: [main] jobs: rspec: From 2dd1eb9e3fbaaf3693b9a32414fb8cf7706c9db9 Mon Sep 17 00:00:00 2001 From: Patrik Ragnarsson Date: Wed, 17 Jan 2024 00:02:11 +0100 Subject: [PATCH 25/53] Allow childprocess 5 (#820) I think it only brings improvements: https://github.com/enkessler/childprocess/releases/tag/v5.0.0 --- overcommit.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/overcommit.gemspec b/overcommit.gemspec index ef9f24fc..8bc70845 100644 --- a/overcommit.gemspec +++ b/overcommit.gemspec @@ -27,7 +27,7 @@ Gem::Specification.new do |s| s.required_ruby_version = '>= 2.4' - s.add_dependency 'childprocess', '>= 0.6.3', '< 5' + s.add_dependency 'childprocess', '>= 0.6.3', '< 6' s.add_dependency 'iniparse', '~> 1.4' s.add_dependency 'rexml', '~> 3.2' end From f190f24b748ba04ed5199c9ac8ca12557237800c Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Tue, 16 Jan 2024 15:05:50 -0800 Subject: [PATCH 26/53] Cut version 0.62.0 (#821) --- CHANGELOG.md | 4 ++++ lib/overcommit/version.rb | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc14f3f1..5953a7c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Overcommit Changelog +## 0.62.0 + +* Allow version 5 of `childprocess` gem dependency + ## 0.61.0 * Allow `ReplaceBranch` to use `skip_if` diff --git a/lib/overcommit/version.rb b/lib/overcommit/version.rb index 0646ce48..f6805668 100644 --- a/lib/overcommit/version.rb +++ b/lib/overcommit/version.rb @@ -2,5 +2,5 @@ # Defines the gem version. module Overcommit - VERSION = '0.61.0' + VERSION = '0.62.0' end From 607ce057b760b697dc63623e7b7dc06a79316eab Mon Sep 17 00:00:00 2001 From: benmelz Date: Sat, 24 Feb 2024 18:50:30 -0500 Subject: [PATCH 27/53] Get suite running smoothly again (#824) Am planning on proposing/implementing a new feature, but first I noticed that there are a number of failing specs on main, so I figured I would start with that. As written, this includes four main adjustments, two of which might actually be bugfixes: - one spec was hanging indefinitely for me locally on a `Thread.join` call - explicitly capturing the child threads and joining them directly fixed it (might be machine dependent?) - when an encoding is specified, the rails schema up to date hook was passing arguments incorrectly (kwarg containing `encoding` was being interpreted as the `length` positional arg) (possible bug) - many specs were attempting to create file submodules without the `protocol.file.allow=always` config option causing failure - alias detection for amendment appeared to be broken, due to regexp incompatibilities between ruby/git (git wasn't properly parsing `\s` in the value matcher for `git config --regexp [key] [value]` command), so moved that matching into ruby (possible bug, also maybe machine/git build opt dependent) - dropped ruby 2.6 from the test matrix - it appears that it's far enough EOL that github has trouble even setting it up. I can attempt to add it back/get it working, but I figured it might be time to ditch it *I don't have a windows machine, so I'm not gonna be much help with those CI builds (should note fails appear unrelated to anything I've done here). --- .github/workflows/tests.yml | 1 - .../pre_commit/rails_schema_up_to_date.rb | 4 +-- .../helpers/file_modifications.rb | 31 ++++++++++++------- spec/overcommit/git_repo_spec.rb | 22 +++++++------ .../hook/prepare_commit_msg/base_spec.rb | 4 +-- .../hook_context/commit_msg_spec.rb | 10 +++--- .../hook_context/post_checkout_spec.rb | 2 +- .../hook_context/post_commit_spec.rb | 2 +- .../hook_context/post_merge_spec.rb | 2 +- .../hook_context/post_rewrite_spec.rb | 3 +- .../hook_context/pre_commit_spec.rb | 10 +++--- spec/overcommit/hook_context/run_all_spec.rb | 3 +- spec/overcommit/installer_spec.rb | 2 +- 13 files changed, 54 insertions(+), 42 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 26c20dd1..71a83ba6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -14,7 +14,6 @@ jobs: fail-fast: false matrix: ruby-version: - - '2.6' - '2.7' - '3.0' - '3.1' diff --git a/lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb b/lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb index dafd31a1..1f2de970 100644 --- a/lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb +++ b/lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb @@ -35,7 +35,7 @@ def run # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplex private def encoding - return unless @config.key?('encoding') + return {} unless @config.key?('encoding') { encoding: @config['encoding'] }.compact end @@ -53,7 +53,7 @@ def schema_files end def schema - @schema ||= schema_files.map { |file| File.read(file, encoding) }.join + @schema ||= schema_files.map { |file| File.read(file, **encoding) }.join @schema.tr('_', '') end diff --git a/lib/overcommit/hook_context/helpers/file_modifications.rb b/lib/overcommit/hook_context/helpers/file_modifications.rb index 00aaccc8..8d221ddc 100644 --- a/lib/overcommit/hook_context/helpers/file_modifications.rb +++ b/lib/overcommit/hook_context/helpers/file_modifications.rb @@ -12,7 +12,7 @@ def amendment? cmd = Overcommit::Utils.parent_command return unless cmd - amend_pattern = 'commit(\s.*)?\s--amend(\s|$)' + amend_pattern = /commit(\s.*)?\s--amend/ # Since the ps command can return invalid byte sequences for commands # containing unicode characters, we replace the offending characters, @@ -24,18 +24,11 @@ def amendment? encode('UTF-8') end - return @amendment if - # True if the command is a commit with the --amend flag - @amendment = !(/\s#{amend_pattern}/ =~ cmd).nil? + # True if the command is a commit with the --amend flag + return @amendment if @amendment = cmd.match?(amend_pattern) # Check for git aliases that call `commit --amend` - `git config --get-regexp "^alias\\." "#{amend_pattern}"`. - scan(/alias\.([-\w]+)/). # Extract the alias - each do |match| - return @amendment if - # True if the command uses a git alias for `commit --amend` - @amendment = !(/git(\.exe)?\s+#{match[0]}/ =~ cmd).nil? - end + return @amendment if @amendment = command_is_amend_alias?(cmd, amend_pattern) @amendment end @@ -74,6 +67,22 @@ def modified_lines_in_file(file) end @modified_lines[file] end + + private + + def command_is_amend_alias?(cmd, amend_pattern) + `git config --get-regexp "^alias"`.split("\n").each do |alias_def| + alias_map = alias_def.match /alias\.(?[-\w]+)\s+(?.+)/ + next unless alias_map + + alias_from_match = alias_map[:from].match? amend_pattern + alias_to_match = cmd.match? /git(\.exe)?\s+#{alias_map[:to]}/ + + # True if the command uses a git alias for `commit --amend` + return true if @amendment = alias_from_match && alias_to_match + end + false + end end end end diff --git a/spec/overcommit/git_repo_spec.rb b/spec/overcommit/git_repo_spec.rb index 128737c3..08f3b585 100644 --- a/spec/overcommit/git_repo_spec.rb +++ b/spec/overcommit/git_repo_spec.rb @@ -24,12 +24,13 @@ end submodule = repo do - `git submodule add #{nested_submodule} nested-sub 2>&1 > #{File::NULL}` + git_config = '-c protocol.file.allow=always' + `git #{git_config} submodule add #{nested_submodule} nested-sub 2>&1 > #{File::NULL}` `git commit -m "Add nested submodule"` end repo do - `git submodule add #{submodule} sub 2>&1 > #{File::NULL}` + `git -c protocol.file.allow=always submodule add #{submodule} sub 2>&1 > #{File::NULL}` example.run end end @@ -150,7 +151,7 @@ end before do - `git submodule add #{submodule} sub 2>&1 > #{File::NULL}` + `git -c protocol.file.allow=always submodule add #{submodule} sub 2>&1 > #{File::NULL}` end it { should_not include File.expand_path('sub') } @@ -178,7 +179,8 @@ `git commit --allow-empty -m "Submodule commit"` end - `git submodule add #{submodule} #{submodule_dir} 2>&1 > #{File::NULL}` + git_config = '-c protocol.file.allow=always' + `git #{git_config} submodule add #{submodule} #{submodule_dir} 2>&1 > #{File::NULL}` `git commit -m "Add submodule"` end @@ -282,7 +284,7 @@ touch 'tracked' `git add tracked` `git commit -m "Initial commit"` - `git submodule add #{submodule} sub 2>&1 > #{File::NULL}` + `git -c protocol.file.allow=always submodule add #{submodule} sub 2>&1 > #{File::NULL}` touch 'staged' `git add staged` example.run @@ -327,7 +329,7 @@ end repo do - `git submodule add #{submodule} sub-repo 2>&1 > #{File::NULL}` + `git -c protocol.file.allow=always submodule add #{submodule} sub-repo 2>&1 > #{File::NULL}` `git commit -m "Initial commit"` example.run end @@ -343,7 +345,8 @@ `git commit --allow-empty -m "Another submodule"` end - `git submodule add #{another_submodule} another-sub-repo 2>&1 > #{File::NULL}` + git_config = '-c protocol.file.allow=always' + `git #{git_config} submodule add #{another_submodule} another-sub-repo 2>&1 > #{File::NULL}` end it { should be_empty } @@ -365,11 +368,12 @@ context 'when there are multiple submodule removals staged' do before do - another_submodule = repo do + another_submod = repo do `git commit --allow-empty -m "Another submodule"` end - `git submodule add #{another_submodule} yet-another-sub-repo 2>&1 > #{File::NULL}` + git_conf = '-c protocol.file.allow=always' + `git #{git_conf} submodule add #{another_submod} yet-another-sub-repo 2>&1 > #{File::NULL}` `git commit -m "Add yet another submodule"` `git rm sub-repo` `git rm yet-another-sub-repo` diff --git a/spec/overcommit/hook/prepare_commit_msg/base_spec.rb b/spec/overcommit/hook/prepare_commit_msg/base_spec.rb index 616d6b8e..ef635a48 100644 --- a/spec/overcommit/hook/prepare_commit_msg/base_spec.rb +++ b/spec/overcommit/hook/prepare_commit_msg/base_spec.rb @@ -38,9 +38,7 @@ contents + "bravo\n" end end - Thread.new { hook_1.run } - Thread.new { hook_2.run } - Thread.list.each { |t| t.join unless t == Thread.current } + [Thread.new { hook_1.run }, Thread.new { hook_2.run }].each(&:join) expect(File.read(tempfile)).to match(/alpha\n#{initial_content}bravo\n/m) end end diff --git a/spec/overcommit/hook_context/commit_msg_spec.rb b/spec/overcommit/hook_context/commit_msg_spec.rb index 2aa68516..058f1508 100644 --- a/spec/overcommit/hook_context/commit_msg_spec.rb +++ b/spec/overcommit/hook_context/commit_msg_spec.rb @@ -298,7 +298,7 @@ end repo do - `git submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` echo('Hello World', 'sub/submodule-file') `git submodule foreach "git add submodule-file" < #{File::NULL}` @@ -474,7 +474,7 @@ end repo do - `git submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` echo('Hello World', 'sub/submodule-file') `git submodule foreach "git add submodule-file" < #{File::NULL}` @@ -500,7 +500,7 @@ end repo do - `git submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` echo('Hello World', 'sub/submodule-file') `git submodule foreach "git add submodule-file" < #{File::NULL}` @@ -532,7 +532,7 @@ end repo do - `git submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` `git rm sub` example.run @@ -561,7 +561,7 @@ end repo do - `git submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` + `git -c protocol.file.allow=always submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` expect(subject).to_not include File.expand_path('test-sub') end end diff --git a/spec/overcommit/hook_context/post_checkout_spec.rb b/spec/overcommit/hook_context/post_checkout_spec.rb index 50657c37..df1dccd2 100644 --- a/spec/overcommit/hook_context/post_checkout_spec.rb +++ b/spec/overcommit/hook_context/post_checkout_spec.rb @@ -67,7 +67,7 @@ repo do `git commit --allow-empty -m "Initial commit"` - `git submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` + `git -c protocol.file.allow=always submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` `git commit -m "Add submodule"` expect(subject).to_not include File.expand_path('test-sub') end diff --git a/spec/overcommit/hook_context/post_commit_spec.rb b/spec/overcommit/hook_context/post_commit_spec.rb index 81758256..5322a1f2 100644 --- a/spec/overcommit/hook_context/post_commit_spec.rb +++ b/spec/overcommit/hook_context/post_commit_spec.rb @@ -20,7 +20,7 @@ end repo do - `git submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` + `git -c protocol.file.allow=always submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` `git commit -m "Initial commit"` expect(subject).to_not include File.expand_path('test-sub') end diff --git a/spec/overcommit/hook_context/post_merge_spec.rb b/spec/overcommit/hook_context/post_merge_spec.rb index aa89fa82..0621b695 100644 --- a/spec/overcommit/hook_context/post_merge_spec.rb +++ b/spec/overcommit/hook_context/post_merge_spec.rb @@ -94,7 +94,7 @@ repo do `git commit --allow-empty -m "Initial commit"` `git checkout -b child > #{File::NULL} 2>&1` - `git submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` + `git -c protocol.file.allow=always submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` `git commit -m "Add submodule"` `git checkout master > #{File::NULL} 2>&1` `git merge --no-ff --no-edit child` diff --git a/spec/overcommit/hook_context/post_rewrite_spec.rb b/spec/overcommit/hook_context/post_rewrite_spec.rb index d2f18f6e..0d510c4a 100644 --- a/spec/overcommit/hook_context/post_rewrite_spec.rb +++ b/spec/overcommit/hook_context/post_rewrite_spec.rb @@ -101,8 +101,9 @@ end repo do + git_config = '-c protocol.file.allow=always' `git commit --allow-empty -m "Initial commit"` - `git submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` + `git #{git_config} submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` `git commit --amend -m "Add submodule"` expect(subject).to_not include File.expand_path('test-sub') end diff --git a/spec/overcommit/hook_context/pre_commit_spec.rb b/spec/overcommit/hook_context/pre_commit_spec.rb index dae42e66..719982a1 100644 --- a/spec/overcommit/hook_context/pre_commit_spec.rb +++ b/spec/overcommit/hook_context/pre_commit_spec.rb @@ -207,7 +207,7 @@ end repo do - `git submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` echo('Hello World', 'sub/submodule-file') `git submodule foreach "git add submodule-file" < #{File::NULL}` @@ -383,7 +383,7 @@ end repo do - `git submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` echo('Hello World', 'sub/submodule-file') `git submodule foreach "git add submodule-file" < #{File::NULL}` @@ -409,7 +409,7 @@ end repo do - `git submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` echo('Hello World', 'sub/submodule-file') `git submodule foreach "git add submodule-file" < #{File::NULL}` @@ -441,7 +441,7 @@ end repo do - `git submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` `git rm sub` example.run @@ -470,7 +470,7 @@ end repo do - `git submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` + `git -c protocol.file.allow=always submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` expect(subject).to_not include File.expand_path('test-sub') end end diff --git a/spec/overcommit/hook_context/run_all_spec.rb b/spec/overcommit/hook_context/run_all_spec.rb index 516fb70b..c6696edc 100644 --- a/spec/overcommit/hook_context/run_all_spec.rb +++ b/spec/overcommit/hook_context/run_all_spec.rb @@ -46,7 +46,8 @@ end repo do - `git submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` + git_config = '-c protocol.file.allow=always' + `git #{git_config} submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` example.run end end diff --git a/spec/overcommit/installer_spec.rb b/spec/overcommit/installer_spec.rb index c7cfb05e..8739a70e 100644 --- a/spec/overcommit/installer_spec.rb +++ b/spec/overcommit/installer_spec.rb @@ -231,7 +231,7 @@ def hook_files_installed?(hooks_dir) context 'which has an external git dir' do let(:submodule) { File.join(target, 'submodule') } before do - system 'git', 'submodule', 'add', target, 'submodule', + system 'git', '-c', 'protocol.file.allow=always', 'submodule', 'add', target, 'submodule', chdir: target, out: :close, err: :close end let(:submodule_git_file) { File.join(submodule, '.git') } From 65e211451816710afe3b530d2e319db08f2c2f1b Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Sat, 24 Feb 2024 15:57:56 -0800 Subject: [PATCH 28/53] Revert "Get suite running smoothly again (#824)" (#840) This reverts commit 607ce057b760b697dc63623e7b7dc06a79316eab. Going to try to merge a different branch. --- .github/workflows/tests.yml | 1 + .../pre_commit/rails_schema_up_to_date.rb | 4 +-- .../helpers/file_modifications.rb | 31 +++++++------------ spec/overcommit/git_repo_spec.rb | 22 ++++++------- .../hook/prepare_commit_msg/base_spec.rb | 4 ++- .../hook_context/commit_msg_spec.rb | 10 +++--- .../hook_context/post_checkout_spec.rb | 2 +- .../hook_context/post_commit_spec.rb | 2 +- .../hook_context/post_merge_spec.rb | 2 +- .../hook_context/post_rewrite_spec.rb | 3 +- .../hook_context/pre_commit_spec.rb | 10 +++--- spec/overcommit/hook_context/run_all_spec.rb | 3 +- spec/overcommit/installer_spec.rb | 2 +- 13 files changed, 42 insertions(+), 54 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 71a83ba6..26c20dd1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -14,6 +14,7 @@ jobs: fail-fast: false matrix: ruby-version: + - '2.6' - '2.7' - '3.0' - '3.1' diff --git a/lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb b/lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb index 1f2de970..dafd31a1 100644 --- a/lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb +++ b/lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb @@ -35,7 +35,7 @@ def run # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplex private def encoding - return {} unless @config.key?('encoding') + return unless @config.key?('encoding') { encoding: @config['encoding'] }.compact end @@ -53,7 +53,7 @@ def schema_files end def schema - @schema ||= schema_files.map { |file| File.read(file, **encoding) }.join + @schema ||= schema_files.map { |file| File.read(file, encoding) }.join @schema.tr('_', '') end diff --git a/lib/overcommit/hook_context/helpers/file_modifications.rb b/lib/overcommit/hook_context/helpers/file_modifications.rb index 8d221ddc..00aaccc8 100644 --- a/lib/overcommit/hook_context/helpers/file_modifications.rb +++ b/lib/overcommit/hook_context/helpers/file_modifications.rb @@ -12,7 +12,7 @@ def amendment? cmd = Overcommit::Utils.parent_command return unless cmd - amend_pattern = /commit(\s.*)?\s--amend/ + amend_pattern = 'commit(\s.*)?\s--amend(\s|$)' # Since the ps command can return invalid byte sequences for commands # containing unicode characters, we replace the offending characters, @@ -24,11 +24,18 @@ def amendment? encode('UTF-8') end - # True if the command is a commit with the --amend flag - return @amendment if @amendment = cmd.match?(amend_pattern) + return @amendment if + # True if the command is a commit with the --amend flag + @amendment = !(/\s#{amend_pattern}/ =~ cmd).nil? # Check for git aliases that call `commit --amend` - return @amendment if @amendment = command_is_amend_alias?(cmd, amend_pattern) + `git config --get-regexp "^alias\\." "#{amend_pattern}"`. + scan(/alias\.([-\w]+)/). # Extract the alias + each do |match| + return @amendment if + # True if the command uses a git alias for `commit --amend` + @amendment = !(/git(\.exe)?\s+#{match[0]}/ =~ cmd).nil? + end @amendment end @@ -67,22 +74,6 @@ def modified_lines_in_file(file) end @modified_lines[file] end - - private - - def command_is_amend_alias?(cmd, amend_pattern) - `git config --get-regexp "^alias"`.split("\n").each do |alias_def| - alias_map = alias_def.match /alias\.(?[-\w]+)\s+(?.+)/ - next unless alias_map - - alias_from_match = alias_map[:from].match? amend_pattern - alias_to_match = cmd.match? /git(\.exe)?\s+#{alias_map[:to]}/ - - # True if the command uses a git alias for `commit --amend` - return true if @amendment = alias_from_match && alias_to_match - end - false - end end end end diff --git a/spec/overcommit/git_repo_spec.rb b/spec/overcommit/git_repo_spec.rb index 08f3b585..128737c3 100644 --- a/spec/overcommit/git_repo_spec.rb +++ b/spec/overcommit/git_repo_spec.rb @@ -24,13 +24,12 @@ end submodule = repo do - git_config = '-c protocol.file.allow=always' - `git #{git_config} submodule add #{nested_submodule} nested-sub 2>&1 > #{File::NULL}` + `git submodule add #{nested_submodule} nested-sub 2>&1 > #{File::NULL}` `git commit -m "Add nested submodule"` end repo do - `git -c protocol.file.allow=always submodule add #{submodule} sub 2>&1 > #{File::NULL}` + `git submodule add #{submodule} sub 2>&1 > #{File::NULL}` example.run end end @@ -151,7 +150,7 @@ end before do - `git -c protocol.file.allow=always submodule add #{submodule} sub 2>&1 > #{File::NULL}` + `git submodule add #{submodule} sub 2>&1 > #{File::NULL}` end it { should_not include File.expand_path('sub') } @@ -179,8 +178,7 @@ `git commit --allow-empty -m "Submodule commit"` end - git_config = '-c protocol.file.allow=always' - `git #{git_config} submodule add #{submodule} #{submodule_dir} 2>&1 > #{File::NULL}` + `git submodule add #{submodule} #{submodule_dir} 2>&1 > #{File::NULL}` `git commit -m "Add submodule"` end @@ -284,7 +282,7 @@ touch 'tracked' `git add tracked` `git commit -m "Initial commit"` - `git -c protocol.file.allow=always submodule add #{submodule} sub 2>&1 > #{File::NULL}` + `git submodule add #{submodule} sub 2>&1 > #{File::NULL}` touch 'staged' `git add staged` example.run @@ -329,7 +327,7 @@ end repo do - `git -c protocol.file.allow=always submodule add #{submodule} sub-repo 2>&1 > #{File::NULL}` + `git submodule add #{submodule} sub-repo 2>&1 > #{File::NULL}` `git commit -m "Initial commit"` example.run end @@ -345,8 +343,7 @@ `git commit --allow-empty -m "Another submodule"` end - git_config = '-c protocol.file.allow=always' - `git #{git_config} submodule add #{another_submodule} another-sub-repo 2>&1 > #{File::NULL}` + `git submodule add #{another_submodule} another-sub-repo 2>&1 > #{File::NULL}` end it { should be_empty } @@ -368,12 +365,11 @@ context 'when there are multiple submodule removals staged' do before do - another_submod = repo do + another_submodule = repo do `git commit --allow-empty -m "Another submodule"` end - git_conf = '-c protocol.file.allow=always' - `git #{git_conf} submodule add #{another_submod} yet-another-sub-repo 2>&1 > #{File::NULL}` + `git submodule add #{another_submodule} yet-another-sub-repo 2>&1 > #{File::NULL}` `git commit -m "Add yet another submodule"` `git rm sub-repo` `git rm yet-another-sub-repo` diff --git a/spec/overcommit/hook/prepare_commit_msg/base_spec.rb b/spec/overcommit/hook/prepare_commit_msg/base_spec.rb index ef635a48..616d6b8e 100644 --- a/spec/overcommit/hook/prepare_commit_msg/base_spec.rb +++ b/spec/overcommit/hook/prepare_commit_msg/base_spec.rb @@ -38,7 +38,9 @@ contents + "bravo\n" end end - [Thread.new { hook_1.run }, Thread.new { hook_2.run }].each(&:join) + Thread.new { hook_1.run } + Thread.new { hook_2.run } + Thread.list.each { |t| t.join unless t == Thread.current } expect(File.read(tempfile)).to match(/alpha\n#{initial_content}bravo\n/m) end end diff --git a/spec/overcommit/hook_context/commit_msg_spec.rb b/spec/overcommit/hook_context/commit_msg_spec.rb index 058f1508..2aa68516 100644 --- a/spec/overcommit/hook_context/commit_msg_spec.rb +++ b/spec/overcommit/hook_context/commit_msg_spec.rb @@ -298,7 +298,7 @@ end repo do - `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` echo('Hello World', 'sub/submodule-file') `git submodule foreach "git add submodule-file" < #{File::NULL}` @@ -474,7 +474,7 @@ end repo do - `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` echo('Hello World', 'sub/submodule-file') `git submodule foreach "git add submodule-file" < #{File::NULL}` @@ -500,7 +500,7 @@ end repo do - `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` echo('Hello World', 'sub/submodule-file') `git submodule foreach "git add submodule-file" < #{File::NULL}` @@ -532,7 +532,7 @@ end repo do - `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` `git rm sub` example.run @@ -561,7 +561,7 @@ end repo do - `git -c protocol.file.allow=always submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` + `git submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` expect(subject).to_not include File.expand_path('test-sub') end end diff --git a/spec/overcommit/hook_context/post_checkout_spec.rb b/spec/overcommit/hook_context/post_checkout_spec.rb index df1dccd2..50657c37 100644 --- a/spec/overcommit/hook_context/post_checkout_spec.rb +++ b/spec/overcommit/hook_context/post_checkout_spec.rb @@ -67,7 +67,7 @@ repo do `git commit --allow-empty -m "Initial commit"` - `git -c protocol.file.allow=always submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` + `git submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` `git commit -m "Add submodule"` expect(subject).to_not include File.expand_path('test-sub') end diff --git a/spec/overcommit/hook_context/post_commit_spec.rb b/spec/overcommit/hook_context/post_commit_spec.rb index 5322a1f2..81758256 100644 --- a/spec/overcommit/hook_context/post_commit_spec.rb +++ b/spec/overcommit/hook_context/post_commit_spec.rb @@ -20,7 +20,7 @@ end repo do - `git -c protocol.file.allow=always submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` + `git submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` `git commit -m "Initial commit"` expect(subject).to_not include File.expand_path('test-sub') end diff --git a/spec/overcommit/hook_context/post_merge_spec.rb b/spec/overcommit/hook_context/post_merge_spec.rb index 0621b695..aa89fa82 100644 --- a/spec/overcommit/hook_context/post_merge_spec.rb +++ b/spec/overcommit/hook_context/post_merge_spec.rb @@ -94,7 +94,7 @@ repo do `git commit --allow-empty -m "Initial commit"` `git checkout -b child > #{File::NULL} 2>&1` - `git -c protocol.file.allow=always submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` + `git submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` `git commit -m "Add submodule"` `git checkout master > #{File::NULL} 2>&1` `git merge --no-ff --no-edit child` diff --git a/spec/overcommit/hook_context/post_rewrite_spec.rb b/spec/overcommit/hook_context/post_rewrite_spec.rb index 0d510c4a..d2f18f6e 100644 --- a/spec/overcommit/hook_context/post_rewrite_spec.rb +++ b/spec/overcommit/hook_context/post_rewrite_spec.rb @@ -101,9 +101,8 @@ end repo do - git_config = '-c protocol.file.allow=always' `git commit --allow-empty -m "Initial commit"` - `git #{git_config} submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` + `git submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` `git commit --amend -m "Add submodule"` expect(subject).to_not include File.expand_path('test-sub') end diff --git a/spec/overcommit/hook_context/pre_commit_spec.rb b/spec/overcommit/hook_context/pre_commit_spec.rb index 719982a1..dae42e66 100644 --- a/spec/overcommit/hook_context/pre_commit_spec.rb +++ b/spec/overcommit/hook_context/pre_commit_spec.rb @@ -207,7 +207,7 @@ end repo do - `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` echo('Hello World', 'sub/submodule-file') `git submodule foreach "git add submodule-file" < #{File::NULL}` @@ -383,7 +383,7 @@ end repo do - `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` echo('Hello World', 'sub/submodule-file') `git submodule foreach "git add submodule-file" < #{File::NULL}` @@ -409,7 +409,7 @@ end repo do - `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` echo('Hello World', 'sub/submodule-file') `git submodule foreach "git add submodule-file" < #{File::NULL}` @@ -441,7 +441,7 @@ end repo do - `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` `git rm sub` example.run @@ -470,7 +470,7 @@ end repo do - `git -c protocol.file.allow=always submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` + `git submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` expect(subject).to_not include File.expand_path('test-sub') end end diff --git a/spec/overcommit/hook_context/run_all_spec.rb b/spec/overcommit/hook_context/run_all_spec.rb index c6696edc..516fb70b 100644 --- a/spec/overcommit/hook_context/run_all_spec.rb +++ b/spec/overcommit/hook_context/run_all_spec.rb @@ -46,8 +46,7 @@ end repo do - git_config = '-c protocol.file.allow=always' - `git #{git_config} submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` + `git submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` example.run end end diff --git a/spec/overcommit/installer_spec.rb b/spec/overcommit/installer_spec.rb index 8739a70e..c7cfb05e 100644 --- a/spec/overcommit/installer_spec.rb +++ b/spec/overcommit/installer_spec.rb @@ -231,7 +231,7 @@ def hook_files_installed?(hooks_dir) context 'which has an external git dir' do let(:submodule) { File.join(target, 'submodule') } before do - system 'git', '-c', 'protocol.file.allow=always', 'submodule', 'add', target, 'submodule', + system 'git', 'submodule', 'add', target, 'submodule', chdir: target, out: :close, err: :close end let(:submodule_git_file) { File.join(submodule, '.git') } From 9c3d118b8f21ef8bf77d9a9dfc62a8051f8078d3 Mon Sep 17 00:00:00 2001 From: Sorin Guga Date: Sun, 25 Feb 2024 01:58:04 +0200 Subject: [PATCH 29/53] Green CI PoC (#833) Cherry-picked commits from #830, #831, #832, #835, #837 and #839. --- .github/workflows/lint.yml | 2 +- .github/workflows/tests.yml | 29 ++++++++----------- Gemfile | 6 +++- .../pre_commit/rails_schema_up_to_date.rb | 2 +- spec/overcommit/git_repo_spec.rb | 20 ++++++++----- .../hook/prepare_commit_msg/base_spec.rb | 6 ++-- .../hook_context/commit_msg_spec.rb | 10 +++---- .../hook_context/pre_commit_spec.rb | 10 +++---- spec/overcommit/installer_spec.rb | 4 +-- 9 files changed, 46 insertions(+), 43 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 8b23cbab..8cf8b4a0 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Ruby uses: ruby/setup-ruby@v1 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 26c20dd1..e9987e06 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -14,25 +14,20 @@ jobs: fail-fast: false matrix: ruby-version: - - '2.6' - - '2.7' - - '3.0' - - '3.1' - - '3.2' + - "2.6" + - "2.7" + - "3.0" + - "3.1" + - "3.2" os: - ubuntu - - windows - - # Tempfile behavior has changed on Ruby 3.1 such that tests - # fail with permission denied. Would welcome a PR with a fix. - exclude: - - ruby-version: '3.1' - os: windows - - ruby-version: '3.2' - os: windows + # At the moment of this commit various specs fail on Windows. + # Any contributor is welcome to fix them and enable the Windows build. + # Please see Issue #836 for more details. + # - windows steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Ruby ${{ matrix.ruby-version }} uses: ruby/setup-ruby@v1 @@ -47,7 +42,7 @@ jobs: bundle exec rspec - name: Code coverage reporting - uses: coverallsapp/github-action@master + uses: coverallsapp/github-action@v2 with: github-token: ${{ secrets.github_token }} flag-name: ruby${{ matrix.ruby-version }}-${{ matrix.os }} @@ -59,7 +54,7 @@ jobs: steps: - name: Finalize code coverage report - uses: coverallsapp/github-action@master + uses: coverallsapp/github-action@v2 with: github-token: ${{ secrets.github_token }} parallel-finished: true diff --git a/Gemfile b/Gemfile index 53b13c7f..49dc7923 100644 --- a/Gemfile +++ b/Gemfile @@ -12,6 +12,10 @@ gem 'simplecov', '~> 0.21.0' gem 'simplecov-lcov', '~> 0.8.0' # Pin RuboCop for CI builds -gem 'rubocop', '1.59.0' +if RUBY_VERSION < '2.7.0' + gem 'rubocop', '1.50.0' +else + gem 'rubocop', '1.59.0' +end gem 'ffi' if Gem.win_platform? diff --git a/lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb b/lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb index dafd31a1..61725074 100644 --- a/lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb +++ b/lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb @@ -53,7 +53,7 @@ def schema_files end def schema - @schema ||= schema_files.map { |file| File.read(file, encoding) }.join + @schema ||= schema_files.map { |file| File.read(file, **(encoding || {})) }.join @schema.tr('_', '') end diff --git a/spec/overcommit/git_repo_spec.rb b/spec/overcommit/git_repo_spec.rb index 128737c3..b887415b 100644 --- a/spec/overcommit/git_repo_spec.rb +++ b/spec/overcommit/git_repo_spec.rb @@ -24,12 +24,13 @@ end submodule = repo do - `git submodule add #{nested_submodule} nested-sub 2>&1 > #{File::NULL}` + `git -c protocol.file.allow=always submodule add \ + #{nested_submodule} nested-sub 2>&1 > #{File::NULL}` `git commit -m "Add nested submodule"` end repo do - `git submodule add #{submodule} sub 2>&1 > #{File::NULL}` + `git -c protocol.file.allow=always submodule add #{submodule} sub 2>&1 > #{File::NULL}` example.run end end @@ -150,7 +151,7 @@ end before do - `git submodule add #{submodule} sub 2>&1 > #{File::NULL}` + `git -c protocol.file.allow=always submodule add #{submodule} sub 2>&1 > #{File::NULL}` end it { should_not include File.expand_path('sub') } @@ -178,7 +179,8 @@ `git commit --allow-empty -m "Submodule commit"` end - `git submodule add #{submodule} #{submodule_dir} 2>&1 > #{File::NULL}` + `git -c protocol.file.allow=always submodule add \ + #{submodule} #{submodule_dir} 2>&1 > #{File::NULL}` `git commit -m "Add submodule"` end @@ -282,7 +284,7 @@ touch 'tracked' `git add tracked` `git commit -m "Initial commit"` - `git submodule add #{submodule} sub 2>&1 > #{File::NULL}` + `git -c protocol.file.allow=always submodule add #{submodule} sub 2>&1 > #{File::NULL}` touch 'staged' `git add staged` example.run @@ -327,7 +329,7 @@ end repo do - `git submodule add #{submodule} sub-repo 2>&1 > #{File::NULL}` + `git -c protocol.file.allow=always submodule add #{submodule} sub-repo 2>&1 > #{File::NULL}` `git commit -m "Initial commit"` example.run end @@ -343,7 +345,8 @@ `git commit --allow-empty -m "Another submodule"` end - `git submodule add #{another_submodule} another-sub-repo 2>&1 > #{File::NULL}` + `git -c protocol.file.allow=always submodule add \ + #{another_submodule} another-sub-repo 2>&1 > #{File::NULL}` end it { should be_empty } @@ -369,7 +372,8 @@ `git commit --allow-empty -m "Another submodule"` end - `git submodule add #{another_submodule} yet-another-sub-repo 2>&1 > #{File::NULL}` + `git -c protocol.file.allow=always submodule add \ + #{another_submodule} yet-another-sub-repo 2>&1 > #{File::NULL}` `git commit -m "Add yet another submodule"` `git rm sub-repo` `git rm yet-another-sub-repo` diff --git a/spec/overcommit/hook/prepare_commit_msg/base_spec.rb b/spec/overcommit/hook/prepare_commit_msg/base_spec.rb index 616d6b8e..873ed637 100644 --- a/spec/overcommit/hook/prepare_commit_msg/base_spec.rb +++ b/spec/overcommit/hook/prepare_commit_msg/base_spec.rb @@ -38,9 +38,9 @@ contents + "bravo\n" end end - Thread.new { hook_1.run } - Thread.new { hook_2.run } - Thread.list.each { |t| t.join unless t == Thread.current } + t1 = Thread.new { hook_1.run } + t2 = Thread.new { hook_2.run } + [t1, t2].each(&:join) expect(File.read(tempfile)).to match(/alpha\n#{initial_content}bravo\n/m) end end diff --git a/spec/overcommit/hook_context/commit_msg_spec.rb b/spec/overcommit/hook_context/commit_msg_spec.rb index 2aa68516..058f1508 100644 --- a/spec/overcommit/hook_context/commit_msg_spec.rb +++ b/spec/overcommit/hook_context/commit_msg_spec.rb @@ -298,7 +298,7 @@ end repo do - `git submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` echo('Hello World', 'sub/submodule-file') `git submodule foreach "git add submodule-file" < #{File::NULL}` @@ -474,7 +474,7 @@ end repo do - `git submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` echo('Hello World', 'sub/submodule-file') `git submodule foreach "git add submodule-file" < #{File::NULL}` @@ -500,7 +500,7 @@ end repo do - `git submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` echo('Hello World', 'sub/submodule-file') `git submodule foreach "git add submodule-file" < #{File::NULL}` @@ -532,7 +532,7 @@ end repo do - `git submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` `git rm sub` example.run @@ -561,7 +561,7 @@ end repo do - `git submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` + `git -c protocol.file.allow=always submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` expect(subject).to_not include File.expand_path('test-sub') end end diff --git a/spec/overcommit/hook_context/pre_commit_spec.rb b/spec/overcommit/hook_context/pre_commit_spec.rb index dae42e66..719982a1 100644 --- a/spec/overcommit/hook_context/pre_commit_spec.rb +++ b/spec/overcommit/hook_context/pre_commit_spec.rb @@ -207,7 +207,7 @@ end repo do - `git submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` echo('Hello World', 'sub/submodule-file') `git submodule foreach "git add submodule-file" < #{File::NULL}` @@ -383,7 +383,7 @@ end repo do - `git submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` echo('Hello World', 'sub/submodule-file') `git submodule foreach "git add submodule-file" < #{File::NULL}` @@ -409,7 +409,7 @@ end repo do - `git submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` echo('Hello World', 'sub/submodule-file') `git submodule foreach "git add submodule-file" < #{File::NULL}` @@ -441,7 +441,7 @@ end repo do - `git submodule add #{submodule} sub > #{File::NULL} 2>&1` + `git -c protocol.file.allow=always submodule add #{submodule} sub > #{File::NULL} 2>&1` `git commit -m "Add submodule"` `git rm sub` example.run @@ -470,7 +470,7 @@ end repo do - `git submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` + `git -c protocol.file.allow=always submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` expect(subject).to_not include File.expand_path('test-sub') end end diff --git a/spec/overcommit/installer_spec.rb b/spec/overcommit/installer_spec.rb index c7cfb05e..5283b2b6 100644 --- a/spec/overcommit/installer_spec.rb +++ b/spec/overcommit/installer_spec.rb @@ -231,8 +231,8 @@ def hook_files_installed?(hooks_dir) context 'which has an external git dir' do let(:submodule) { File.join(target, 'submodule') } before do - system 'git', 'submodule', 'add', target, 'submodule', - chdir: target, out: :close, err: :close + system 'git', '-c', 'protocol.file.allow=always', 'submodule', 'add', target, + 'submodule', chdir: target, out: :close, err: :close end let(:submodule_git_file) { File.join(submodule, '.git') } let(:submodule_git_dir) do From a2fb742f28407c9a762d60ae723a796b6472667c Mon Sep 17 00:00:00 2001 From: Sorin Guga Date: Sun, 25 Feb 2024 02:05:52 +0200 Subject: [PATCH 30/53] [FEATURE] New pre-commit hook: Sorbet (Issue #825) (#826) ## Introduction This pre-commit hook runs the Sorbet type-checker. [More information about Sorbet here](https://sorbet.org/docs/overview) Fixes #825 ## Requirements [Sorbet](https://github.com/sorbet/sorbet) Notes: not sure if this should be a pre-commit hook or pre-push hook to be honest. Co-authored-by: Shane da Silva --- README.md | 66 +++++++++++-------- config/default.yml | 8 +++ lib/overcommit/hook/pre_commit/sorbet.rb | 24 +++++++ .../overcommit/hook/pre_commit/sorbet_spec.rb | 54 +++++++++++++++ 4 files changed, 124 insertions(+), 28 deletions(-) create mode 100644 lib/overcommit/hook/pre_commit/sorbet.rb create mode 100644 spec/overcommit/hook/pre_commit/sorbet_spec.rb diff --git a/README.md b/README.md index afcbcbbf..769c1cf1 100644 --- a/README.md +++ b/README.md @@ -17,34 +17,43 @@ are stored in source control. You can also easily [add your existing hook scripts](#adding-existing-git-hooks) without writing any Ruby code. -* [Requirements](#requirements) - * [Dependencies](#dependencies) -* [Installation](#installation) - * [Automatically Install Overcommit Hooks](#automatically-install-overcommit-hooks) -* [Usage](#usage) -* [Continuous Integration](#continuous-integration) -* [Configuration](#configuration) - * [Hook Options](#hook-options) - * [Hook Categories](#hook-categories) - * [Gemfile](#gemfile) - * [Plugin Directory](#plugin-directory) - * [Signature Verification](#signature-verification) -* [Built-In Hooks](#built-in-hooks) - * [CommitMsg](#commitmsg) - * [PostCheckout](#postcheckout) - * [PostCommit](#postcommit) - * [PostMerge](#postmerge) - * [PostRewrite](#postrewrite) - * [PreCommit](#precommit) - * [PrePush](#prepush) - * [PreRebase](#prerebase) -* [Repo-Specific Hooks](#repo-specific-hooks) - * [Adding Existing Git Hooks](#adding-existing-git-hooks) -* [Security](#security) -* [Contributing](#contributing) -* [Community](#community) -* [Changelog](#changelog) -* [License](#license) +- [Requirements](#requirements) + - [Windows](#windows) + - [Dependencies](#dependencies) +- [Installation](#installation) + - [Automatically Install Overcommit Hooks](#automatically-install-overcommit-hooks) +- [Usage](#usage) + - [Skipping Hooks](#skipping-hooks) + - [Disabling Overcommit](#disabling-overcommit) + - [Disabling Colorized Output](#disabling-colorized-output) +- [Continuous Integration](#continuous-integration) +- [Configuration](#configuration) + - [Hook Options](#hook-options) + - [Hook Categories](#hook-categories) + - [The `ALL` Hook](#the-all-hook) + - [Gemfile](#gemfile) + - [Plugin Directory](#plugin-directory) + - [Quiet Hook Runs](#quiet-hook-runs) + - [Concurrency](#concurrency) + - [Signature Verification](#signature-verification) +- [Built-In Hooks](#built-in-hooks) + - [CommitMsg](#commitmsg) + - [PostCheckout](#postcheckout) + - [PostCommit](#postcommit) + - [PostMerge](#postmerge) + - [PostRewrite](#postrewrite) + - [PreCommit](#precommit) + - [WARNING: pre-commit hooks cannot have side effects](#warning-pre-commit-hooks-cannot-have-side-effects) + - [PrePush](#prepush) + - [PreRebase](#prerebase) +- [Repo-Specific hooks](#repo-specific-hooks) + - [Adding Existing Git Hooks](#adding-existing-git-hooks) +- [Security](#security) + - [Disabling Signature Checking](#disabling-signature-checking) +- [Contributing](#contributing) +- [Community](#community) +- [Changelog](#changelog) +- [License](#license) ## Requirements @@ -561,6 +570,7 @@ issue](https://github.com/sds/overcommit/issues/238) for more details. * [SemiStandard](lib/overcommit/hook/pre_commit/semi_standard.rb) * [ShellCheck](lib/overcommit/hook/pre_commit/shell_check.rb) * [SlimLint](lib/overcommit/hook/pre_commit/slim_lint.rb) +* [Sorbet](lib/overcommit/hook/pre_commit/sorbet.rb) * [Sqlint](lib/overcommit/hook/pre_commit/sqlint.rb) * [Standard](lib/overcommit/hook/pre_commit/standard.rb) * [Stylelint](lib/overcommit/hook/pre_commit/stylelint.rb) diff --git a/config/default.yml b/config/default.yml index 181187af..e0fc3910 100644 --- a/config/default.yml +++ b/config/default.yml @@ -790,6 +790,14 @@ PreCommit: install_command: 'gem install slim_lint' include: '**/*.slim' + Sorbet: + enabled: false + description: 'Analyze with Sorbet' + required_executable: 'srb' + install_command: 'gem install sorbet' + command: ['srb', 'tc'] + include: '**/*.rb' + Sqlint: enabled: false description: 'Analyze with sqlint' diff --git a/lib/overcommit/hook/pre_commit/sorbet.rb b/lib/overcommit/hook/pre_commit/sorbet.rb new file mode 100644 index 00000000..57988a6e --- /dev/null +++ b/lib/overcommit/hook/pre_commit/sorbet.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module Overcommit::Hook::PreCommit + # Runs 'srb tc' against any modified files. + # + # @see https://github.com/sorbet/sorbet + class Sorbet < Base + # example of output: + # sorbet.rb:1: Method `foo` does not exist on `T.class_of(Bar)` https://srb.help/7003 + MESSAGE_REGEX = /^(?[^:]+):(?\d+): (?.*)$/.freeze + + def run + result = execute(command, args: applicable_files) + return :pass if result.success? + + output = result.stderr.split("\n").grep(MESSAGE_REGEX) + + extract_messages( + output, + MESSAGE_REGEX + ) + end + end +end diff --git a/spec/overcommit/hook/pre_commit/sorbet_spec.rb b/spec/overcommit/hook/pre_commit/sorbet_spec.rb new file mode 100644 index 00000000..60f811cb --- /dev/null +++ b/spec/overcommit/hook/pre_commit/sorbet_spec.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Overcommit::Hook::PreCommit::Sorbet do + let(:config) { Overcommit::ConfigurationLoader.default_configuration } + let(:context) { double('context') } + subject { described_class.new(config, context) } + + before do + subject.stub(:applicable_files).and_return(%w[file1.rb file2.rb]) + end + + context 'when Sorbet exits successfully' do + let(:result) { double('result') } + + before do + result.stub(:success?).and_return(true) + subject.stub(:execute).and_return(result) + end + + it { should pass } + + context 'and it printed a message to stderr' do + before do + result.stub(:stderr).and_return("No errors! Great job.\n") + end + + it { should pass } + end + end + + context 'when Sorbet exits unsucessfully' do + let(:result) { double('result') } + + before do + result.stub(:success?).and_return(false) + subject.stub(:execute).and_return(result) + end + + context 'and it reports an error' do + before do + result.stub(:stderr).and_return(normalize_indent(<<-MSG)) + sorbet.rb:1: Method `foo` does not exist on `T.class_of(Bar)` https://srb.help/7003 + 5 | foo 'bar' + ^^^ + Errors: 1 + MSG + end + + it { should fail_hook } + end + end +end From c4aa796d09ac5a432501a37cf270f8edc6aa4cb2 Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Sat, 24 Feb 2024 16:12:12 -0800 Subject: [PATCH 31/53] Fix RuboCop warnings (#841) --- .rubocop.yml | 4 +++- lib/overcommit/cli.rb | 16 +++++++--------- lib/overcommit/hook/base.rb | 14 ++++++-------- lib/overcommit/hook/commit_msg/text_width.rb | 2 +- lib/overcommit/hook/pre_commit/erb_lint.rb | 2 +- lib/overcommit/hook/pre_commit/html_hint.rb | 2 +- lib/overcommit/hook/pre_commit/json_syntax.rb | 10 ++++------ lib/overcommit/hook/pre_commit/xml_syntax.rb | 10 ++++------ lib/overcommit/hook/pre_commit/yaml_syntax.rb | 16 +++++++--------- lib/overcommit/utils/messages_utils.rb | 2 +- overcommit.gemspec | 2 +- 11 files changed, 36 insertions(+), 44 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 8c779097..1b4e7ad7 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,7 +1,9 @@ inherit_from: .rubocop_todo.yml AllCops: - TargetRubyVersion: 2.4 + TargetRubyVersion: 2.6 + NewCops: disable + SuggestExtensions: false Layout/ClosingParenthesisIndentation: Enabled: false diff --git a/lib/overcommit/cli.rb b/lib/overcommit/cli.rb index bc2ec994..f8127125 100644 --- a/lib/overcommit/cli.rb +++ b/lib/overcommit/cli.rb @@ -124,15 +124,13 @@ def install_or_uninstall end @options[:targets].each do |target| - begin - Installer.new(log).run(target, @options) - rescue Overcommit::Exceptions::InvalidGitRepo => e - log.warning "Invalid repo #{target}: #{e}" - halt 69 # EX_UNAVAILABLE - rescue Overcommit::Exceptions::PreExistingHooks => e - log.warning "Unable to install into #{target}: #{e}" - halt 73 # EX_CANTCREAT - end + Installer.new(log).run(target, @options) + rescue Overcommit::Exceptions::InvalidGitRepo => e + log.warning "Invalid repo #{target}: #{e}" + halt 69 # EX_UNAVAILABLE + rescue Overcommit::Exceptions::PreExistingHooks => e + log.warning "Unable to install into #{target}: #{e}" + halt 73 # EX_CANTCREAT end end diff --git a/lib/overcommit/hook/base.rb b/lib/overcommit/hook/base.rb index 37696d08..3c2eaeb3 100644 --- a/lib/overcommit/hook/base.rb +++ b/lib/overcommit/hook/base.rb @@ -228,14 +228,12 @@ def check_for_libraries output = [] required_libraries.each do |library| - begin - require library - rescue LoadError - install_command = @config['install_command'] - install_command = " -- install via #{install_command}" if install_command - - output << "Unable to load '#{library}'#{install_command}" - end + require library + rescue LoadError + install_command = @config['install_command'] + install_command = " -- install via #{install_command}" if install_command + + output << "Unable to load '#{library}'#{install_command}" end return if output.empty? diff --git a/lib/overcommit/hook/commit_msg/text_width.rb b/lib/overcommit/hook/commit_msg/text_width.rb index 63addbcf..52de3bd7 100644 --- a/lib/overcommit/hook/commit_msg/text_width.rb +++ b/lib/overcommit/hook/commit_msg/text_width.rb @@ -41,7 +41,7 @@ def find_errors_in_body(lines) max_body_width = config['max_body_width'] - lines[2..-1].each_with_index do |line, index| + lines[2..].each_with_index do |line, index| if line.chomp.size > max_body_width @errors << "Line #{index + 3} of commit message has > " \ "#{max_body_width} characters" diff --git a/lib/overcommit/hook/pre_commit/erb_lint.rb b/lib/overcommit/hook/pre_commit/erb_lint.rb index a903b10b..ae5af164 100644 --- a/lib/overcommit/hook/pre_commit/erb_lint.rb +++ b/lib/overcommit/hook/pre_commit/erb_lint.rb @@ -12,7 +12,7 @@ def run return :pass if result.success? extract_messages( - result.stdout.split("\n\n")[1..-1], + result.stdout.split("\n\n")[1..], MESSAGE_REGEX ) end diff --git a/lib/overcommit/hook/pre_commit/html_hint.rb b/lib/overcommit/hook/pre_commit/html_hint.rb index e8cb4a68..ddbe37d1 100644 --- a/lib/overcommit/hook/pre_commit/html_hint.rb +++ b/lib/overcommit/hook/pre_commit/html_hint.rb @@ -14,7 +14,7 @@ def run lines = group.split("\n").map(&:strip) file = lines[0][/(.+):/, 1] extract_messages( - lines[1..-1].map { |msg| "#{file}: #{msg}" }, + lines[1..].map { |msg| "#{file}: #{msg}" }, /^(?(?:\w:)?[^:]+): line (?\d+)/ ) end.flatten diff --git a/lib/overcommit/hook/pre_commit/json_syntax.rb b/lib/overcommit/hook/pre_commit/json_syntax.rb index 04972b91..bd162f7d 100644 --- a/lib/overcommit/hook/pre_commit/json_syntax.rb +++ b/lib/overcommit/hook/pre_commit/json_syntax.rb @@ -7,12 +7,10 @@ def run messages = [] applicable_files.each do |file| - begin - JSON.parse(IO.read(file)) - rescue JSON::ParserError => e - error = "#{e.message} parsing #{file}" - messages << Overcommit::Hook::Message.new(:error, file, nil, error) - end + JSON.parse(IO.read(file)) + rescue JSON::ParserError => e + error = "#{e.message} parsing #{file}" + messages << Overcommit::Hook::Message.new(:error, file, nil, error) end messages diff --git a/lib/overcommit/hook/pre_commit/xml_syntax.rb b/lib/overcommit/hook/pre_commit/xml_syntax.rb index 7ac05360..99465182 100644 --- a/lib/overcommit/hook/pre_commit/xml_syntax.rb +++ b/lib/overcommit/hook/pre_commit/xml_syntax.rb @@ -7,12 +7,10 @@ def run messages = [] applicable_files.each do |file| - begin - REXML::Document.new(IO.read(file)) - rescue REXML::ParseException => e - error = "Error parsing #{file}: #{e.message}" - messages << Overcommit::Hook::Message.new(:error, file, nil, error) - end + REXML::Document.new(IO.read(file)) + rescue REXML::ParseException => e + error = "Error parsing #{file}: #{e.message}" + messages << Overcommit::Hook::Message.new(:error, file, nil, error) end messages diff --git a/lib/overcommit/hook/pre_commit/yaml_syntax.rb b/lib/overcommit/hook/pre_commit/yaml_syntax.rb index dd685450..83ff6789 100644 --- a/lib/overcommit/hook/pre_commit/yaml_syntax.rb +++ b/lib/overcommit/hook/pre_commit/yaml_syntax.rb @@ -7,17 +7,15 @@ def run messages = [] applicable_files.each do |file| + YAML.load_file(file, aliases: true) + rescue ArgumentError begin - YAML.load_file(file, aliases: true) - rescue ArgumentError - begin - YAML.load_file(file) - rescue ArgumentError, Psych::SyntaxError => e - messages << Overcommit::Hook::Message.new(:error, file, nil, e.message) - end - rescue Psych::DisallowedClass => e - messages << error_message(file, e) + YAML.load_file(file) + rescue ArgumentError, Psych::SyntaxError => e + messages << Overcommit::Hook::Message.new(:error, file, nil, e.message) end + rescue Psych::DisallowedClass => e + messages << error_message(file, e) end messages diff --git a/lib/overcommit/utils/messages_utils.rb b/lib/overcommit/utils/messages_utils.rb index c92a6010..31c0f8db 100644 --- a/lib/overcommit/utils/messages_utils.rb +++ b/lib/overcommit/utils/messages_utils.rb @@ -26,7 +26,7 @@ def extract_messages(output_messages, regex, type_categorizer = nil) raise Overcommit::Exceptions::MessageProcessingError, 'Unexpected output: unable to determine line number or type ' \ "of error/warning for output:\n" \ - "#{output_messages[index..-1].join("\n")}" + "#{output_messages[index..].join("\n")}" end file = extract_file(match, message) diff --git a/overcommit.gemspec b/overcommit.gemspec index 8bc70845..268a9fc1 100644 --- a/overcommit.gemspec +++ b/overcommit.gemspec @@ -25,7 +25,7 @@ Gem::Specification.new do |s| Dir['libexec/**/*'] + Dir['template-dir/**/*'] - s.required_ruby_version = '>= 2.4' + s.required_ruby_version = '>= 2.6' s.add_dependency 'childprocess', '>= 0.6.3', '< 6' s.add_dependency 'iniparse', '~> 1.4' From b58b6358e7e8d8a278d4ebba83a5b4a68d2f0058 Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Sat, 24 Feb 2024 16:18:43 -0800 Subject: [PATCH 32/53] Add RSpec Hook to PreCommit, Add Applicable files if set (#842) - **Add RSpec to pre_commit hooks** - **Add applicable files to RSpec command if include configuration set** - **Fix RuboCop errors** --------- Co-authored-by: Max Prettyjohns --- config/default.yml | 5 + lib/overcommit/hook/pre_commit/r_spec.rb | 12 ++ lib/overcommit/hook/pre_push/r_spec.rb | 12 +- lib/overcommit/hook/shared/r_spec.rb | 21 ++++ .../overcommit/hook/pre_commit/r_spec_spec.rb | 116 ++++++++++++++++++ spec/overcommit/hook/pre_push/r_spec_spec.rb | 36 ++++++ 6 files changed, 194 insertions(+), 8 deletions(-) create mode 100644 lib/overcommit/hook/pre_commit/r_spec.rb create mode 100644 lib/overcommit/hook/shared/r_spec.rb create mode 100644 spec/overcommit/hook/pre_commit/r_spec_spec.rb diff --git a/config/default.yml b/config/default.yml index e0fc3910..70ae0b2d 100644 --- a/config/default.yml +++ b/config/default.yml @@ -709,6 +709,11 @@ PreCommit: install_command: 'pip install restructuredtext_lint' include: '**/*.rst' + RSpec: + enabled: false + description: 'Run tests with Rspec' + required_executable: 'rspec' + RuboCop: enabled: false description: 'Analyze with RuboCop' diff --git a/lib/overcommit/hook/pre_commit/r_spec.rb b/lib/overcommit/hook/pre_commit/r_spec.rb new file mode 100644 index 00000000..26bbc0a8 --- /dev/null +++ b/lib/overcommit/hook/pre_commit/r_spec.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +require 'overcommit/hook/shared/r_spec' + +module Overcommit::Hook::PreCommit + # Runs `rspec` test suite + # + # @see http://rspec.info/ + class RSpec < Base + include Overcommit::Hook::Shared::RSpec + end +end diff --git a/lib/overcommit/hook/pre_push/r_spec.rb b/lib/overcommit/hook/pre_push/r_spec.rb index a3b4474c..7ce3df29 100644 --- a/lib/overcommit/hook/pre_push/r_spec.rb +++ b/lib/overcommit/hook/pre_push/r_spec.rb @@ -1,16 +1,12 @@ # frozen_string_literal: true +require 'overcommit/hook/shared/r_spec' + module Overcommit::Hook::PrePush - # Runs `rspec` test suite before push + # Runs `rspec` test suite # # @see http://rspec.info/ class RSpec < Base - def run - result = execute(command) - return :pass if result.success? - - output = result.stdout + result.stderr - [:fail, output] - end + include Overcommit::Hook::Shared::RSpec end end diff --git a/lib/overcommit/hook/shared/r_spec.rb b/lib/overcommit/hook/shared/r_spec.rb new file mode 100644 index 00000000..9b41e8e1 --- /dev/null +++ b/lib/overcommit/hook/shared/r_spec.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module Overcommit::Hook::Shared + # Runs `rspec` test suite before push + # + # @see http://rspec.info/ + module RSpec + def run + result = if @config['include'] + execute(command, args: applicable_files) + else + execute(command) + end + + return :pass if result.success? + + output = result.stdout + result.stderr + [:fail, output] + end + end +end diff --git a/spec/overcommit/hook/pre_commit/r_spec_spec.rb b/spec/overcommit/hook/pre_commit/r_spec_spec.rb new file mode 100644 index 00000000..7fdff3b3 --- /dev/null +++ b/spec/overcommit/hook/pre_commit/r_spec_spec.rb @@ -0,0 +1,116 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Overcommit::Hook::PreCommit::RSpec do + let(:config) { Overcommit::ConfigurationLoader.default_configuration } + let(:context) { double('context') } + subject { described_class.new(config, context) } + + context 'when rspec exits successfully' do + let(:result) { double('result') } + + before do + result.stub(:success?).and_return(true) + subject.stub(:execute).and_return(result) + end + + it { should pass } + + it { + expect(subject).to receive(:execute).with(['rspec']).and_return(result) + + subject.run + } + end + + context 'with included files set' do + let(:result) { double('result') } + let(:config) do + super().merge(Overcommit::Configuration.new( + 'PreCommit' => { + 'RSpec' => { + 'include' => ['**/*_spec.rb'], + } + } + )) + end + + let(:context) { double('context') } + + before do + result.stub(:success?).and_return(true) + subject.stub(:execute).and_return(result) + subject.stub(:applicable_files).and_return('spec/test_spec.rb') + end + + it { should pass } + + it { + expect(subject).to receive(:execute).with(['rspec'], + args: 'spec/test_spec.rb').and_return(result) + + subject.run + } + end + + context 'when rspec exits unsuccessfully' do + let(:result) { double('result') } + + before do + result.stub(:success?).and_return(false) + subject.stub(:execute).and_return(result) + end + + context 'with a runtime error' do + before do + result.stub(stdout: '', stderr: <<-MSG) + /home/user/.rbenv/gems/2.2.0/gems/rspec-core-3.2.2/lib/rspec/core/configuration.rb:1226:in `load': /home/user/dev/github/overcommit/spec/overcommit/hook/pre_push/rspec_spec.rb:49: can't find string "EOS" anywhere before EOF (SyntaxError) + /home/user/dev/overcommit/spec/overcommit/hook/pre_push/rspec_spec.rb:29: syntax error, unexpected end-of-input + from /home/user/.rbenv/gems/2.2.0/gems/rspec-core-3.2.2/lib/rspec/core/configuration.rb:1226:in `block in load_spec_files' + from /home/user/.rbenv/gems/2.2.0/gems/rspec-core-3.2.2/lib/rspec/core/configuration.rb:1224:in `each' + from /home/user/.rbenv/gems/2.2.0/gems/rspec-core-3.2.2/lib/rspec/core/configuration.rb:1224:in `load_spec_files' + from /home/user/.rbenv/gems/2.2.0/gems/rspec-core-3.2.2/lib/rspec/core/runner.rb:97:in `setup' + from /home/user/.rbenv/gems/2.2.0/gems/rspec-core-3.2.2/lib/rspec/core/runner.rb:85:in `run' + from /home/user/.rbenv/gems/2.2.0/gems/rspec-core-3.2.2/lib/rspec/core/runner.rb:70:in `run' + from /home/user/.rbenv/gems/2.2.0/gems/rspec-core-3.2.2/lib/rspec/core/runner.rb:38:in `invoke' + from /home/user/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/rspec-core-3.2.2/exe/rspec:4:in `' + from /home/user/.rbenv/versions/2.2.1/bin/rspec:23:in `load' + from /home/user/.rbenv/versions/2.2.1/bin/rspec:23:in `
' + MSG + end + + it { should fail_hook } + end + + context 'with a test failure' do + before do + result.stub(stderr: '', stdout: <<-MSG) + .FF + + Failures: + + 1) Overcommit::Hook::PrePush::RSpec when rspec exits unsuccessfully with a runtime error should fail + Failure/Error: it { should fail_hook } + expected that the hook would fail + # ./spec/overcommit/hook/pre_push/rspec_spec.rb:45:in `block (4 levels) in ' + + 2) Overcommit::Hook::PrePush::RSpec when rspec exits unsuccessfully with a test failure should fail + Failure/Error: it { should fail_hook } + expected that the hook would fail + # ./spec/overcommit/hook/pre_push/rspec_spec.rb:57:in `block (4 levels) in ' + + Finished in 0.00505 seconds (files took 0.27437 seconds to load) + 3 examples, 2 failures + + Failed examples: + + rspec ./spec/overcommit/hook/pre_push/rspec_spec.rb:45 # Overcommit::Hook::PrePush::RSpec when rspec exits unsuccessfully with a runtime error should fail + rspec ./spec/overcommit/hook/pre_push/rspec_spec.rb:57 # Overcommit::Hook::PrePush::RSpec when rspec exits unsuccessfully with a test failure should fail + MSG + end + + it { should fail_hook } + end + end +end diff --git a/spec/overcommit/hook/pre_push/r_spec_spec.rb b/spec/overcommit/hook/pre_push/r_spec_spec.rb index 26f6ea0f..1efc56d7 100644 --- a/spec/overcommit/hook/pre_push/r_spec_spec.rb +++ b/spec/overcommit/hook/pre_push/r_spec_spec.rb @@ -16,6 +16,42 @@ end it { should pass } + + it { + expect(subject).to receive(:execute).with(['rspec']).and_return(result) + + subject.run + } + end + + context 'with included files set' do + let(:result) { double('result') } + let(:config) do + super().merge(Overcommit::Configuration.new( + 'PrePush' => { + 'RSpec' => { + 'include' => ['**/*_spec.rb'], + } + } + )) + end + + let(:context) { double('context') } + + before do + result.stub(:success?).and_return(true) + subject.stub(:execute).and_return(result) + subject.stub(:applicable_files).and_return('spec/test_spec.rb') + end + + it { should pass } + + it { + expect(subject).to receive(:execute).with(['rspec'], + args: 'spec/test_spec.rb').and_return(result) + + subject.run + } end context 'when rspec exits unsuccessfully' do From b700bd25723fe0a731c2102d33b42d5e5d760d80 Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Sat, 24 Feb 2024 16:24:07 -0800 Subject: [PATCH 33/53] Cut version 0.63.0 (#843) --- CHANGELOG.md | 5 +++++ lib/overcommit/version.rb | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5953a7c1..f61b7d5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Overcommit Changelog +## 0.63.0 + +* Add `Sorbet` pre-commit hook +* Add `RSpec` pre-commit hook + ## 0.62.0 * Allow version 5 of `childprocess` gem dependency diff --git a/lib/overcommit/version.rb b/lib/overcommit/version.rb index f6805668..e640bf38 100644 --- a/lib/overcommit/version.rb +++ b/lib/overcommit/version.rb @@ -2,5 +2,5 @@ # Defines the gem version. module Overcommit - VERSION = '0.62.0' + VERSION = '0.63.0' end From 7974b3b08ee8e78ace35ee0472698c830ac08104 Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Sat, 24 Feb 2024 16:28:42 -0800 Subject: [PATCH 34/53] Fix README badges (#844) --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 769c1cf1..4ad91913 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ [![Gem Version](https://badge.fury.io/rb/overcommit.svg)](https://badge.fury.io/rb/overcommit) -[![Build Status](https://github.com/sds/overcommit/actions/workflows/tests.yml/badge.svg?branch=master)](https://github.com/sds/overcommit/actions/workflows/tests.yml/badge.svg?branch=master) -[![Coverage Status](https://coveralls.io/repos/github/sds/overcommit/badge.svg?branch=master)](https://coveralls.io/github/sds/overcommit?branch=master) +[![Build Status](https://github.com/sds/overcommit/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/sds/overcommit/actions/workflows/tests.yml/badge.svg?branch=main) +[![Coverage Status](https://coveralls.io/repos/github/sds/overcommit/badge.svg?branch=main)](https://coveralls.io/github/sds/overcommit?branch=main) [![Maintainability](https://api.codeclimate.com/v1/badges/5da42f7f365e5fef6b4c/maintainability)](https://codeclimate.com/github/sds/overcommit/maintainability) -[![Inline docs](http://inch-ci.org/github/sds/overcommit.svg?branch=master)](http://inch-ci.org/github/sds/overcommit) +[![Inline docs](http://inch-ci.org/github/sds/overcommit.svg?branch=main)](http://inch-ci.org/github/sds/overcommit)

Overcommit Logo From a14ec6330c778bae3df46fce8b6a640ee74e8d37 Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Sat, 24 Feb 2024 16:35:08 -0800 Subject: [PATCH 35/53] Update README with latest requirements (#845) Clarify Windows support is now best effort, given we don't have tests. --- README.md | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 4ad91913..877e9396 100644 --- a/README.md +++ b/README.md @@ -57,15 +57,9 @@ any Ruby code. ## Requirements -This project aims to support the following Ruby runtimes on both \*nix and Windows: +This project aims to support the following Ruby runtimes on \*nix (and best effort on Windows): -* Ruby 2.4+ - -### Windows - -If you are using Overcommit on **Windows**, make sure you include the `ffi` gem in your -list of dependencies. Overcommit does not include the `ffi` gem by default since it -significantly increases the install time for non-Windows platforms. +* Ruby 2.6+ ### Dependencies From 841954c64954818be1d246ec01b72f922ca28faa Mon Sep 17 00:00:00 2001 From: Matt Brictson Date: Sat, 11 May 2024 23:36:11 -0700 Subject: [PATCH 36/53] Add Ruby 3.3 to CI matrix (#849) It might be a good idea to also update the `main` branch protection rules to require that the 3.2 and 3.3 jobs succeed. Right now only 2.7, 3.0, and 3.1 are required. A repository admin will need to make this change. --- .github/workflows/tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e9987e06..0e2aac20 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,6 +19,7 @@ jobs: - "3.0" - "3.1" - "3.2" + - "3.3" os: - ubuntu # At the moment of this commit various specs fail on Windows. From 0e717f97a60e88ddd0b8a408b84f4420d7bda1a8 Mon Sep 17 00:00:00 2001 From: Matt Brictson Date: Sat, 11 May 2024 23:36:50 -0700 Subject: [PATCH 37/53] Support stylelint 16+, which emits messages on stderr (#848) Before Stylelint 16, Stylelint emitted its messages on stdout. Hence Overcommit's Stylelint hook was built to read output from stdout. Starting with Stylelint 16, Stylelint now emits its messages to stderr, which means the existing Overcommit implementation no longer works. This PR updates Overcommit's Stylelint plugin to check for messages on _both_ stdout and stderr. That way <16 and >=16 versions of Stylelint are supported. Fixes #823 --- lib/overcommit/hook/pre_commit/stylelint.rb | 2 +- .../hook/pre_commit/stylelint_spec.rb | 29 ++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/overcommit/hook/pre_commit/stylelint.rb b/lib/overcommit/hook/pre_commit/stylelint.rb index b129cbd2..aae26f08 100644 --- a/lib/overcommit/hook/pre_commit/stylelint.rb +++ b/lib/overcommit/hook/pre_commit/stylelint.rb @@ -12,7 +12,7 @@ class Stylelint < Base def run result = execute(command, args: applicable_files) - output = result.stdout.chomp + output = result.stdout + result.stderr.chomp return :pass if result.success? && output.empty? extract_messages( diff --git a/spec/overcommit/hook/pre_commit/stylelint_spec.rb b/spec/overcommit/hook/pre_commit/stylelint_spec.rb index d31ba948..68e83f65 100644 --- a/spec/overcommit/hook/pre_commit/stylelint_spec.rb +++ b/spec/overcommit/hook/pre_commit/stylelint_spec.rb @@ -15,6 +15,7 @@ before do result = double('result') result.stub(:success?).and_return(true) + result.stub(:stderr).and_return('') result.stub(:stdout).and_return('') subject.stub(:execute).and_return(result) end @@ -22,7 +23,7 @@ it { should pass } end - context 'when stylelint exits unsucessfully' do + context 'when stylelint exits unsucessfully with messages on stdout (stylelint < 16)' do let(:result) { double('result') } before do @@ -32,6 +33,7 @@ context 'and it reports an error' do before do result.stub(:success?).and_return(false) + result.stub(:stderr).and_return('') result.stub(:stdout).and_return([ 'index.css: line 4, col 4, error - Expected indentation of 2 spaces (indentation)', 'form.css: line 10, col 6, error - Expected indentation of 4 spaces (indentation)', @@ -45,4 +47,29 @@ end end end + + context 'when stylelint exits unsucessfully with messages on stderr (stylelint >= 16)' do + let(:result) { double('result') } + + before do + subject.stub(:execute).and_return(result) + end + + context 'and it reports an error' do + before do + result.stub(:success?).and_return(false) + result.stub(:stdout).and_return('') + result.stub(:stderr).and_return([ + 'index.css: line 4, col 4, error - Expected indentation of 2 spaces (indentation)', + 'form.css: line 10, col 6, error - Expected indentation of 4 spaces (indentation)', + ].join("\n")) + end + + it { should fail_hook } + + it 'extracts lines numbers correctly from output' do + expect(subject.run.map(&:line)).to eq([4, 10]) + end + end + end end From 26e78aa9e5e907ed41ebdac8098483af4d54865c Mon Sep 17 00:00:00 2001 From: fynsta <63241108+fynsta@users.noreply.github.com> Date: Mon, 24 Jun 2024 20:54:52 +0200 Subject: [PATCH 38/53] Add changelog_uri to gemspec (#851) Supported here: https://guides.rubygems.org/specification-reference/#metadata Useful for running https://github.com/MaximeD/gem_updater --- overcommit.gemspec | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/overcommit.gemspec b/overcommit.gemspec index 268a9fc1..0b3a590d 100644 --- a/overcommit.gemspec +++ b/overcommit.gemspec @@ -15,6 +15,10 @@ Gem::Specification.new do |s| s.post_install_message = 'Install hooks by running `overcommit --install` in your Git repository' + s.metadata = { + 'changelog_uri' => 'https://github.com/sds/overcommit/blob/main/CHANGELOG.md' + } + s.require_paths = %w[lib] s.executables = ['overcommit'] From 939d9e6be210fb59b453e3ce18abf4409d105503 Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Mon, 22 Jul 2024 13:48:43 -0700 Subject: [PATCH 39/53] Cut version 0.64.0 (#852) --- lib/overcommit/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/overcommit/version.rb b/lib/overcommit/version.rb index e640bf38..9df380b0 100644 --- a/lib/overcommit/version.rb +++ b/lib/overcommit/version.rb @@ -2,5 +2,5 @@ # Defines the gem version. module Overcommit - VERSION = '0.63.0' + VERSION = '0.64.0' end From 5ff9d5e78906813fc9421f2ce9388aee9363b8bf Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Mon, 22 Jul 2024 13:52:53 -0700 Subject: [PATCH 40/53] Update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f61b7d5c..d8d2133f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Overcommit Changelog +## 0.64.0 + +* Add support for `stylelint` 16+ +* Add `changelog_uri` to gemspec + ## 0.63.0 * Add `Sorbet` pre-commit hook From 5a3d68eaa70573bb600bb9deedda0e5d622eafea Mon Sep 17 00:00:00 2001 From: Joakim Antman Date: Sun, 11 Aug 2024 09:31:18 +0300 Subject: [PATCH 41/53] Fix spec compatibility with recent git versions (#854) The original array was defining the shellwords like this: `["git", "commit", "-m", "\"Resolve", "conflicts\"", "-i", "some-file"]` This combined with the most recent git version failed with: ``` error: pathspec 'conflicts"' did not match any file(s) known to git ``` This PR just simplifies the commit message to work with the %w array literal. --- spec/integration/resolving_cherry_pick_conflict_spec.rb | 2 +- spec/integration/resolving_merge_conflict_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/integration/resolving_cherry_pick_conflict_spec.rb b/spec/integration/resolving_cherry_pick_conflict_spec.rb index 58e22e65..2a7f053c 100644 --- a/spec/integration/resolving_cherry_pick_conflict_spec.rb +++ b/spec/integration/resolving_cherry_pick_conflict_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe 'resolving cherry-pick conflicts' do - subject { shell(%w[git commit -m "Resolve conflicts" -i some-file]) } + subject { shell(%w[git commit -m Test -i some-file]) } let(:config) { <<-YML } PreCommit: diff --git a/spec/integration/resolving_merge_conflict_spec.rb b/spec/integration/resolving_merge_conflict_spec.rb index 679ba136..997dcb09 100644 --- a/spec/integration/resolving_merge_conflict_spec.rb +++ b/spec/integration/resolving_merge_conflict_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe 'resolving merge conflicts' do - subject { shell(%w[git commit -m "Resolve conflicts" -i some-file]) } + subject { shell(%w[git commit -m Test -i some-file]) } around do |example| repo do From 31c83ce603008de3ac04ff9b7d1ea9fca6e529c8 Mon Sep 17 00:00:00 2001 From: Joakim Antman Date: Sun, 11 Aug 2024 09:37:24 +0300 Subject: [PATCH 42/53] Expand tildes(~) for hooksPath (#853) While installing overcommit git hooks i noticed that tildes are not expanded to home folders for the `hooksPath` config, the result was a tilde folder in the current directory. This PR addresses that by switching `File.absolute_path` to `File.expand_path`. The [underlaying implementation](https://github.com/ruby/ruby/blob/v3_3_4/file.c#L3753) in Ruby is exactly the same just with this difference in how `~` is handled. --------- Co-authored-by: Shane da Silva --- lib/overcommit/git_config.rb | 2 +- spec/overcommit/git_config_spec.rb | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/overcommit/git_config.rb b/lib/overcommit/git_config.rb index 392dd9da..c1243861 100644 --- a/lib/overcommit/git_config.rb +++ b/lib/overcommit/git_config.rb @@ -17,7 +17,7 @@ def hooks_path path = `git config --get core.hooksPath`.chomp return File.join(Overcommit::Utils.git_dir, 'hooks') if path.empty? - File.absolute_path(path, Dir.pwd) + File.expand_path(path, Dir.pwd) end end end diff --git a/spec/overcommit/git_config_spec.rb b/spec/overcommit/git_config_spec.rb index 22ad7c02..9cc51862 100644 --- a/spec/overcommit/git_config_spec.rb +++ b/spec/overcommit/git_config_spec.rb @@ -78,5 +78,19 @@ expect(subject).to eq File.expand_path('my-hooks') end end + + context 'when explicitly set to a path starting with a tilde' do + around do |example| + repo do + `git config --local core.hooksPath ~/my-hooks` + example.run + end + end + + it 'returns the absolute path to the folder in the users home path' do + expect(subject).to eq File.expand_path('~/my-hooks') + expect(subject).not_to include('~') + end + end end end From 9825868ba2b2194a2329d24c08d47a054bf265cc Mon Sep 17 00:00:00 2001 From: Edward Woodcock <768254+RemoteCTO@users.noreply.github.com> Date: Thu, 31 Oct 2024 05:47:17 +0100 Subject: [PATCH 43/53] Bump rexml to >= 3.3.9 to resolve GHSA-2rxp-v6pw-ch6m (#857) A `ReDoS vulnerability in REXML` has been identified in versions <3.3.9 Details in GitHub: - https://github.com/ruby/rexml/security/advisories/GHSA-2rxp-v6pw-ch6m This is a small bump to the latest patched version. This should resolve anybody getting the following `bundle audit` error when using overcommit: ``` Name: rexml Version: 3.3.8 CVE: CVE-2024-49761 GHSA: GHSA-2rxp-v6pw-ch6m Criticality: High URL: https://github.com/ruby/rexml/security/advisories/GHSA-2rxp-v6pw-ch6m Title: REXML ReDoS vulnerability Solution: update to '>= 3.3.9' ``` --- lib/overcommit/version.rb | 2 +- overcommit.gemspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/overcommit/version.rb b/lib/overcommit/version.rb index 9df380b0..afd18470 100644 --- a/lib/overcommit/version.rb +++ b/lib/overcommit/version.rb @@ -2,5 +2,5 @@ # Defines the gem version. module Overcommit - VERSION = '0.64.0' + VERSION = '0.64.1' end diff --git a/overcommit.gemspec b/overcommit.gemspec index 0b3a590d..caaa8499 100644 --- a/overcommit.gemspec +++ b/overcommit.gemspec @@ -33,5 +33,5 @@ Gem::Specification.new do |s| s.add_dependency 'childprocess', '>= 0.6.3', '< 6' s.add_dependency 'iniparse', '~> 1.4' - s.add_dependency 'rexml', '~> 3.2' + s.add_dependency 'rexml', '>= 3.3.9' end From eff94a7f058d9eeca3f30e069fadba5a82f43da2 Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Wed, 30 Oct 2024 21:49:26 -0700 Subject: [PATCH 44/53] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8d2133f..1ba199d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Overcommit Changelog +## 0.64.1 + +* Update minimum version of rexml to address [CVE-2024-49761](https://www.ruby-lang.org/en/news/2024/10/28/redos-rexml-cve-2024-49761/) + ## 0.64.0 * Add support for `stylelint` 16+ From 7d3e8fa5ed9feb07a57e7fec685a46ccd58769ee Mon Sep 17 00:00:00 2001 From: Carlos Palhares Date: Mon, 27 Jan 2025 16:26:12 -0300 Subject: [PATCH 45/53] Load bundled gems on expected version (#859) Fixes https://github.com/sds/overcommit/issues/789 `psych` is no longer a default gem, but current and old ruby still ships with it. When we `require 'yaml'`, we activate that gem in whatever version that is bundled with ruby. Later on, we load bundler, and we `Bundler.setup`, which will then activate whatever version specified in the lock file. More often than not, they might not match. The approach in this PR is to strip the `yaml` dependency completely from the hook scripts, while retaining the ability to configure the Gemfile using it. --- template-dir/hooks/commit-msg | 10 ++-------- template-dir/hooks/overcommit-hook | 10 ++-------- template-dir/hooks/post-checkout | 10 ++-------- template-dir/hooks/post-commit | 10 ++-------- template-dir/hooks/post-merge | 10 ++-------- template-dir/hooks/post-rewrite | 10 ++-------- template-dir/hooks/pre-commit | 10 ++-------- template-dir/hooks/pre-push | 10 ++-------- template-dir/hooks/pre-rebase | 10 ++-------- template-dir/hooks/prepare-commit-msg | 10 ++-------- 10 files changed, 20 insertions(+), 80 deletions(-) diff --git a/template-dir/hooks/commit-msg b/template-dir/hooks/commit-msg index 7f8023de..377c892b 100755 --- a/template-dir/hooks/commit-msg +++ b/template-dir/hooks/commit-msg @@ -27,14 +27,8 @@ if hook_type == 'overcommit-hook' end # Check if Overcommit should invoke a Bundler context for loading gems -require 'yaml' -# rubocop:disable Style/RescueModifier -gemfile = - begin - YAML.load_file('.overcommit.yml', aliases: true)['gemfile'] - rescue ArgumentError - YAML.load_file('.overcommit.yml')['gemfile'] - end rescue nil +config = File.read('.overcommit.yml') =~ /gemfile: ['"]?(.*)['"]?/ +gemfile = Regexp.last_match(1) if gemfile ENV['BUNDLE_GEMFILE'] = gemfile diff --git a/template-dir/hooks/overcommit-hook b/template-dir/hooks/overcommit-hook index 7f8023de..377c892b 100755 --- a/template-dir/hooks/overcommit-hook +++ b/template-dir/hooks/overcommit-hook @@ -27,14 +27,8 @@ if hook_type == 'overcommit-hook' end # Check if Overcommit should invoke a Bundler context for loading gems -require 'yaml' -# rubocop:disable Style/RescueModifier -gemfile = - begin - YAML.load_file('.overcommit.yml', aliases: true)['gemfile'] - rescue ArgumentError - YAML.load_file('.overcommit.yml')['gemfile'] - end rescue nil +config = File.read('.overcommit.yml') =~ /gemfile: ['"]?(.*)['"]?/ +gemfile = Regexp.last_match(1) if gemfile ENV['BUNDLE_GEMFILE'] = gemfile diff --git a/template-dir/hooks/post-checkout b/template-dir/hooks/post-checkout index 7f8023de..377c892b 100755 --- a/template-dir/hooks/post-checkout +++ b/template-dir/hooks/post-checkout @@ -27,14 +27,8 @@ if hook_type == 'overcommit-hook' end # Check if Overcommit should invoke a Bundler context for loading gems -require 'yaml' -# rubocop:disable Style/RescueModifier -gemfile = - begin - YAML.load_file('.overcommit.yml', aliases: true)['gemfile'] - rescue ArgumentError - YAML.load_file('.overcommit.yml')['gemfile'] - end rescue nil +config = File.read('.overcommit.yml') =~ /gemfile: ['"]?(.*)['"]?/ +gemfile = Regexp.last_match(1) if gemfile ENV['BUNDLE_GEMFILE'] = gemfile diff --git a/template-dir/hooks/post-commit b/template-dir/hooks/post-commit index 7f8023de..377c892b 100755 --- a/template-dir/hooks/post-commit +++ b/template-dir/hooks/post-commit @@ -27,14 +27,8 @@ if hook_type == 'overcommit-hook' end # Check if Overcommit should invoke a Bundler context for loading gems -require 'yaml' -# rubocop:disable Style/RescueModifier -gemfile = - begin - YAML.load_file('.overcommit.yml', aliases: true)['gemfile'] - rescue ArgumentError - YAML.load_file('.overcommit.yml')['gemfile'] - end rescue nil +config = File.read('.overcommit.yml') =~ /gemfile: ['"]?(.*)['"]?/ +gemfile = Regexp.last_match(1) if gemfile ENV['BUNDLE_GEMFILE'] = gemfile diff --git a/template-dir/hooks/post-merge b/template-dir/hooks/post-merge index 7f8023de..377c892b 100755 --- a/template-dir/hooks/post-merge +++ b/template-dir/hooks/post-merge @@ -27,14 +27,8 @@ if hook_type == 'overcommit-hook' end # Check if Overcommit should invoke a Bundler context for loading gems -require 'yaml' -# rubocop:disable Style/RescueModifier -gemfile = - begin - YAML.load_file('.overcommit.yml', aliases: true)['gemfile'] - rescue ArgumentError - YAML.load_file('.overcommit.yml')['gemfile'] - end rescue nil +config = File.read('.overcommit.yml') =~ /gemfile: ['"]?(.*)['"]?/ +gemfile = Regexp.last_match(1) if gemfile ENV['BUNDLE_GEMFILE'] = gemfile diff --git a/template-dir/hooks/post-rewrite b/template-dir/hooks/post-rewrite index 7f8023de..377c892b 100755 --- a/template-dir/hooks/post-rewrite +++ b/template-dir/hooks/post-rewrite @@ -27,14 +27,8 @@ if hook_type == 'overcommit-hook' end # Check if Overcommit should invoke a Bundler context for loading gems -require 'yaml' -# rubocop:disable Style/RescueModifier -gemfile = - begin - YAML.load_file('.overcommit.yml', aliases: true)['gemfile'] - rescue ArgumentError - YAML.load_file('.overcommit.yml')['gemfile'] - end rescue nil +config = File.read('.overcommit.yml') =~ /gemfile: ['"]?(.*)['"]?/ +gemfile = Regexp.last_match(1) if gemfile ENV['BUNDLE_GEMFILE'] = gemfile diff --git a/template-dir/hooks/pre-commit b/template-dir/hooks/pre-commit index 7f8023de..377c892b 100755 --- a/template-dir/hooks/pre-commit +++ b/template-dir/hooks/pre-commit @@ -27,14 +27,8 @@ if hook_type == 'overcommit-hook' end # Check if Overcommit should invoke a Bundler context for loading gems -require 'yaml' -# rubocop:disable Style/RescueModifier -gemfile = - begin - YAML.load_file('.overcommit.yml', aliases: true)['gemfile'] - rescue ArgumentError - YAML.load_file('.overcommit.yml')['gemfile'] - end rescue nil +config = File.read('.overcommit.yml') =~ /gemfile: ['"]?(.*)['"]?/ +gemfile = Regexp.last_match(1) if gemfile ENV['BUNDLE_GEMFILE'] = gemfile diff --git a/template-dir/hooks/pre-push b/template-dir/hooks/pre-push index 7f8023de..377c892b 100755 --- a/template-dir/hooks/pre-push +++ b/template-dir/hooks/pre-push @@ -27,14 +27,8 @@ if hook_type == 'overcommit-hook' end # Check if Overcommit should invoke a Bundler context for loading gems -require 'yaml' -# rubocop:disable Style/RescueModifier -gemfile = - begin - YAML.load_file('.overcommit.yml', aliases: true)['gemfile'] - rescue ArgumentError - YAML.load_file('.overcommit.yml')['gemfile'] - end rescue nil +config = File.read('.overcommit.yml') =~ /gemfile: ['"]?(.*)['"]?/ +gemfile = Regexp.last_match(1) if gemfile ENV['BUNDLE_GEMFILE'] = gemfile diff --git a/template-dir/hooks/pre-rebase b/template-dir/hooks/pre-rebase index 7f8023de..377c892b 100755 --- a/template-dir/hooks/pre-rebase +++ b/template-dir/hooks/pre-rebase @@ -27,14 +27,8 @@ if hook_type == 'overcommit-hook' end # Check if Overcommit should invoke a Bundler context for loading gems -require 'yaml' -# rubocop:disable Style/RescueModifier -gemfile = - begin - YAML.load_file('.overcommit.yml', aliases: true)['gemfile'] - rescue ArgumentError - YAML.load_file('.overcommit.yml')['gemfile'] - end rescue nil +config = File.read('.overcommit.yml') =~ /gemfile: ['"]?(.*)['"]?/ +gemfile = Regexp.last_match(1) if gemfile ENV['BUNDLE_GEMFILE'] = gemfile diff --git a/template-dir/hooks/prepare-commit-msg b/template-dir/hooks/prepare-commit-msg index 7f8023de..377c892b 100755 --- a/template-dir/hooks/prepare-commit-msg +++ b/template-dir/hooks/prepare-commit-msg @@ -27,14 +27,8 @@ if hook_type == 'overcommit-hook' end # Check if Overcommit should invoke a Bundler context for loading gems -require 'yaml' -# rubocop:disable Style/RescueModifier -gemfile = - begin - YAML.load_file('.overcommit.yml', aliases: true)['gemfile'] - rescue ArgumentError - YAML.load_file('.overcommit.yml')['gemfile'] - end rescue nil +config = File.read('.overcommit.yml') =~ /gemfile: ['"]?(.*)['"]?/ +gemfile = Regexp.last_match(1) if gemfile ENV['BUNDLE_GEMFILE'] = gemfile From 9ce54927dda3fdc7de00fbfcf68a9ebaf9e008c3 Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Mon, 27 Jan 2025 11:27:56 -0800 Subject: [PATCH 46/53] Cut version 0.65.0 --- CHANGELOG.md | 4 ++++ lib/overcommit/version.rb | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ba199d2..bbe08fb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Overcommit Changelog +## 0.65.0 + +* Load bundled gems on expected version + ## 0.64.1 * Update minimum version of rexml to address [CVE-2024-49761](https://www.ruby-lang.org/en/news/2024/10/28/redos-rexml-cve-2024-49761/) diff --git a/lib/overcommit/version.rb b/lib/overcommit/version.rb index afd18470..0b718a39 100644 --- a/lib/overcommit/version.rb +++ b/lib/overcommit/version.rb @@ -2,5 +2,5 @@ # Defines the gem version. module Overcommit - VERSION = '0.64.1' + VERSION = '0.65.0' end From b4d4ce0e819dad926dfd0073540dd73a5217e2e9 Mon Sep 17 00:00:00 2001 From: benmelz Date: Wed, 29 Jan 2025 19:26:01 -0500 Subject: [PATCH 47/53] Add `-diff` cli option for running precommit hooks against diffs (#860) For example, running `overcommit --diff main` from a feature branch will run pre-commit hooks against the diff between the two branches. I was able to very easily leverage existing code for the bulk of the feature - this is mainly just adding the cli option, a hook context to do the execution and some tests based on the existing `--run-all` test. --- For background, my team is responsible for a couple of really old, really large rails apps. Getting them completely in compliance with our various linters is a huge task that isn't getting done anytime soon (things are funky to the point that we've even observed breakages with "safe" auto-correct functions). I introduced/started heavily encouraging overcommit so that we at least don't add _new_ linting offenses and things will naturally improve over time. It's been great, but offenses still slip through though here and there, especially with juniors who might be getting away with not having a local install (and/or abusing `OVERCOMMIT_DISABLE=1`). An option like this would allow me to leverage the very useful "only apply to changed lines" logic within a ci environment and help enforce my desired "no new linting offenses" policy. --- lib/overcommit/cli.rb | 23 +++- lib/overcommit/hook_context.rb | 4 +- lib/overcommit/hook_context/base.rb | 4 +- lib/overcommit/hook_context/diff.rb | 37 ++++++ spec/integration/diff_flag_spec.rb | 39 ++++++ spec/overcommit/cli_spec.rb | 26 ++++ spec/overcommit/hook_context/diff_spec.rb | 143 ++++++++++++++++++++++ 7 files changed, 272 insertions(+), 4 deletions(-) create mode 100644 lib/overcommit/hook_context/diff.rb create mode 100644 spec/integration/diff_flag_spec.rb create mode 100644 spec/overcommit/hook_context/diff_spec.rb diff --git a/lib/overcommit/cli.rb b/lib/overcommit/cli.rb index f8127125..dafc545a 100644 --- a/lib/overcommit/cli.rb +++ b/lib/overcommit/cli.rb @@ -9,6 +9,7 @@ module Overcommit class CLI # rubocop:disable Metrics/ClassLength def initialize(arguments, input, logger) @arguments = arguments + @cli_options = {} @input = input @log = logger @options = {} @@ -28,6 +29,8 @@ def run sign when :run_all run_all + when :diff + diff end rescue Overcommit::Exceptions::ConfigurationSignatureChanged => e puts e @@ -45,7 +48,7 @@ def parse_arguments @parser = create_option_parser begin - @parser.parse!(@arguments) + @parser.parse!(@arguments, into: @cli_options) # Default action is to install @options[:action] ||= :install @@ -98,6 +101,11 @@ def add_installation_options(opts) @options[:action] = :run_all @options[:hook_to_run] = arg ? arg.to_s : 'run-all' end + + opts.on('--diff [ref]', 'Run pre_commit hooks against the diff between a given ref. Defaults to `main`.') do |arg| # rubocop:disable Layout/LineLength + @options[:action] = :diff + arg + end end def add_other_options(opts) @@ -209,6 +217,19 @@ def run_all halt(status ? 0 : 65) end + def diff + empty_stdin = File.open(File::NULL) # pre-commit hooks don't take input + context = Overcommit::HookContext.create('diff', config, @arguments, empty_stdin, **@cli_options) # rubocop:disable Layout/LineLength + config.apply_environment!(context, ENV) + + printer = Overcommit::Printer.new(config, log, context) + runner = Overcommit::HookRunner.new(config, log, context, printer) + + status = runner.run + + halt(status ? 0 : 65) + end + # Used for ease of stubbing in tests def halt(status = 0) exit status diff --git a/lib/overcommit/hook_context.rb b/lib/overcommit/hook_context.rb index acdff1bb..5863ed94 100644 --- a/lib/overcommit/hook_context.rb +++ b/lib/overcommit/hook_context.rb @@ -2,13 +2,13 @@ # Utility module which manages the creation of {HookContext}s. module Overcommit::HookContext - def self.create(hook_type, config, args, input) + def self.create(hook_type, config, args, input, **cli_options) hook_type_class = Overcommit::Utils.camel_case(hook_type) underscored_hook_type = Overcommit::Utils.snake_case(hook_type) require "overcommit/hook_context/#{underscored_hook_type}" - Overcommit::HookContext.const_get(hook_type_class).new(config, args, input) + Overcommit::HookContext.const_get(hook_type_class).new(config, args, input, **cli_options) rescue LoadError, NameError => e # Could happen when a symlink was created for a hook type Overcommit does # not yet support. diff --git a/lib/overcommit/hook_context/base.rb b/lib/overcommit/hook_context/base.rb index 077394fb..b50698c9 100644 --- a/lib/overcommit/hook_context/base.rb +++ b/lib/overcommit/hook_context/base.rb @@ -18,10 +18,12 @@ class Base # @param config [Overcommit::Configuration] # @param args [Array] # @param input [IO] standard input stream - def initialize(config, args, input) + # @param options [Hash] cli options + def initialize(config, args, input, **options) @config = config @args = args @input = input + @options = options end # Executes a command as if it were a regular git hook, passing all diff --git a/lib/overcommit/hook_context/diff.rb b/lib/overcommit/hook_context/diff.rb new file mode 100644 index 00000000..0c4b97e0 --- /dev/null +++ b/lib/overcommit/hook_context/diff.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require 'overcommit/git_repo' + +module Overcommit::HookContext + # Simulates a pre-commit context based on the diff with another git ref. + # + # This results in pre-commit hooks running against the changes between the current + # and another ref, which is useful for automated CI scripts. + class Diff < Base + def modified_files + @modified_files ||= Overcommit::GitRepo.modified_files(refs: @options[:diff]) + end + + def modified_lines_in_file(file) + @modified_lines ||= {} + @modified_lines[file] ||= Overcommit::GitRepo.extract_modified_lines(file, + refs: @options[:diff]) + end + + def hook_class_name + 'PreCommit' + end + + def hook_type_name + 'pre_commit' + end + + def hook_script_name + 'pre-commit' + end + + def initial_commit? + @initial_commit ||= Overcommit::GitRepo.initial_commit? + end + end +end diff --git a/spec/integration/diff_flag_spec.rb b/spec/integration/diff_flag_spec.rb new file mode 100644 index 00000000..dcaa1bd3 --- /dev/null +++ b/spec/integration/diff_flag_spec.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'overcommit --diff' do + subject { shell(%w[overcommit --diff main]) } + + context 'when using an existing pre-commit hook script' do + let(:script_name) { 'test-script' } + let(:script_contents) { "#!/bin/bash\nexit 0" } + let(:script_path) { ".#{Overcommit::OS::SEPARATOR}#{script_name}" } + + let(:config) do + { + 'PreCommit' => { + 'MyHook' => { + 'enabled' => true, + 'required_executable' => script_path, + } + } + } + end + + around do |example| + repo do + File.open('.overcommit.yml', 'w') { |f| f.puts(config.to_yaml) } + echo(script_contents, script_path) + `git add #{script_path}` + FileUtils.chmod(0o755, script_path) + example.run + end + end + + it 'completes successfully without blocking' do + wait_until(timeout: 10) { subject } # Need to wait long time for JRuby startup + subject.status.should == 0 + end + end +end diff --git a/spec/overcommit/cli_spec.rb b/spec/overcommit/cli_spec.rb index 40923ad3..3d95b09d 100644 --- a/spec/overcommit/cli_spec.rb +++ b/spec/overcommit/cli_spec.rb @@ -2,6 +2,7 @@ require 'spec_helper' require 'overcommit/cli' +require 'overcommit/hook_context/diff' require 'overcommit/hook_context/run_all' describe Overcommit::CLI do @@ -125,5 +126,30 @@ subject end end + + context 'with the diff switch specified' do + let(:arguments) { ['--diff=some-ref'] } + let(:config) { Overcommit::ConfigurationLoader.default_configuration } + + before do + cli.stub(:halt) + Overcommit::HookRunner.any_instance.stub(:run) + end + + it 'creates a HookRunner with the diff context' do + Overcommit::HookRunner.should_receive(:new). + with(config, + logger, + instance_of(Overcommit::HookContext::Diff), + instance_of(Overcommit::Printer)). + and_call_original + subject + end + + it 'runs the HookRunner' do + Overcommit::HookRunner.any_instance.should_receive(:run) + subject + end + end end end diff --git a/spec/overcommit/hook_context/diff_spec.rb b/spec/overcommit/hook_context/diff_spec.rb new file mode 100644 index 00000000..0c712fbc --- /dev/null +++ b/spec/overcommit/hook_context/diff_spec.rb @@ -0,0 +1,143 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'overcommit/hook_context/diff' + +describe Overcommit::HookContext::Diff do + let(:config) { double('config') } + let(:args) { [] } + let(:input) { double('input') } + let(:context) { described_class.new(config, args, input, diff: 'master') } + + describe '#modified_files' do + subject { context.modified_files } + + context 'when repo contains no files' do + around do |example| + repo do + `git commit --allow-empty -m "Initial commit"` + `git checkout -b other-branch 2>&1` + example.run + end + end + + it { should be_empty } + end + + context 'when the repo contains files that are unchanged from the ref' do + around do |example| + repo do + touch('some-file') + `git add some-file` + touch('some-other-file') + `git add some-other-file` + `git commit -m "Add files"` + `git checkout -b other-branch 2>&1` + example.run + end + end + + it { should be_empty } + end + + context 'when repo contains files that have been changed from the ref' do + around do |example| + repo do + touch('some-file') + `git add some-file` + touch('some-other-file') + `git add some-other-file` + `git commit -m "Add files"` + `git checkout -b other-branch 2>&1` + File.open('some-file', 'w') { |f| f.write("hello\n") } + `git add some-file` + `git commit -m "Edit file"` + example.run + end + end + + it { should == %w[some-file].map { |file| File.expand_path(file) } } + end + + context 'when repo contains submodules' do + around do |example| + submodule = repo do + touch 'foo' + `git add foo` + `git commit -m "Initial commit"` + end + + repo do + `git submodule add #{submodule} test-sub 2>&1 > #{File::NULL}` + `git commit --allow-empty -m "Initial commit"` + `git checkout -b other-branch 2>&1` + example.run + end + end + + it { should_not include File.expand_path('test-sub') } + end + end + + describe '#modified_lines_in_file' do + let(:modified_file) { 'some-file' } + subject { context.modified_lines_in_file(modified_file) } + + context 'when file contains a trailing newline' do + around do |example| + repo do + touch(modified_file) + `git add #{modified_file}` + `git commit -m "Add file"` + `git checkout -b other-branch 2>&1` + File.open(modified_file, 'w') { |f| (1..3).each { |i| f.write("#{i}\n") } } + `git add #{modified_file}` + `git commit -m "Edit file"` + example.run + end + end + + it { should == Set.new(1..3) } + end + + context 'when file does not contain a trailing newline' do + around do |example| + repo do + touch(modified_file) + `git add #{modified_file}` + `git commit -m "Add file"` + `git checkout -b other-branch 2>&1` + File.open(modified_file, 'w') do |f| + (1..2).each { |i| f.write("#{i}\n") } + f.write(3) + end + `git add #{modified_file}` + `git commit -m "Edit file"` + example.run + end + end + + it { should == Set.new(1..3) } + end + end + + describe '#hook_type_name' do + subject { context.hook_type_name } + + it { should == 'pre_commit' } + end + + describe '#hook_script_name' do + subject { context.hook_script_name } + + it { should == 'pre-commit' } + end + + describe '#initial_commit?' do + subject { context.initial_commit? } + + before { Overcommit::GitRepo.stub(:initial_commit?).and_return(true) } + + it { should == true } + end +end From 43e17fb384e51101cd45449e03d39188f18959f9 Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Wed, 29 Jan 2025 16:32:23 -0800 Subject: [PATCH 48/53] Cut version 0.66.0 (#861) --- CHANGELOG.md | 4 ++++ README.md | 1 + lib/overcommit/version.rb | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbe08fb9..d82b5b50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Overcommit Changelog +## 0.66.0 + +* Add `--diff` CLI option for running pre-commit hooks against only changed files + ## 0.65.0 * Load bundled gems on expected version diff --git a/README.md b/README.md index 877e9396..a0d46726 100644 --- a/README.md +++ b/README.md @@ -131,6 +131,7 @@ Command Line Flag | Description `-f`/`--force` | Don't bail on install if other hooks already exist--overwrite them `-l`/`--list-hooks` | Display all available hooks in the current repository `-r`/`--run` | Run pre-commit hook against all tracked files in repository +`--diff ` | Run pre-commit hook against all changed files relative to `` `-t`/`--template-dir` | Print location of template directory `-h`/`--help` | Show command-line flag documentation `-v`/`--version` | Show version diff --git a/lib/overcommit/version.rb b/lib/overcommit/version.rb index 0b718a39..c1091e52 100644 --- a/lib/overcommit/version.rb +++ b/lib/overcommit/version.rb @@ -2,5 +2,5 @@ # Defines the gem version. module Overcommit - VERSION = '0.65.0' + VERSION = '0.66.0' end From 3db733e5b7dd479baee1c8e587aa86ed73e5011f Mon Sep 17 00:00:00 2001 From: Matt Brictson Date: Sun, 16 Feb 2025 13:04:54 -0800 Subject: [PATCH 49/53] Restore ability to specify "gemfile: false" in config (#863) Setting `gemfile: false` in `.overcommit.yml` is supposed to disable Bundler. However, a recently-introduced bug causes `false` to be interpreted as the name of the gemfile. Bundler looks for a gemfile named "false", which fails, leading overcommit's hooks to crash. This PR fixes the bug by adjusting the regex used to parse the `gemfile:` line in the config. Now, `false` is no longer interpreted as a gemfile name. I added an integration test to verify the fix. Fixes #862 --- spec/integration/gemfile_option_spec.rb | 211 +++++++++++++++--------- template-dir/hooks/commit-msg | 2 +- template-dir/hooks/overcommit-hook | 2 +- template-dir/hooks/post-checkout | 2 +- template-dir/hooks/post-commit | 2 +- template-dir/hooks/post-merge | 2 +- template-dir/hooks/post-rewrite | 2 +- template-dir/hooks/pre-commit | 2 +- template-dir/hooks/pre-push | 2 +- template-dir/hooks/pre-rebase | 2 +- template-dir/hooks/prepare-commit-msg | 2 +- 11 files changed, 144 insertions(+), 87 deletions(-) diff --git a/spec/integration/gemfile_option_spec.rb b/spec/integration/gemfile_option_spec.rb index 7a0175da..a6a6a4ba 100644 --- a/spec/integration/gemfile_option_spec.rb +++ b/spec/integration/gemfile_option_spec.rb @@ -3,99 +3,156 @@ require 'spec_helper' describe 'specifying `gemfile` option in Overcommit configuration' do - let(:repo_root) { File.expand_path(File.join('..', '..'), File.dirname(__FILE__)) } - let(:fake_gem_path) { File.join('lib', 'my_fake_gem') } - - # We point the overcommit gem back to this repo since we can't assume the gem - # has already been installed in a test environment - let(:gemfile) { normalize_indent(<<-RUBY) } - source 'https://rubygems.org' - - gem 'overcommit', path: '#{repo_root}' - gem 'my_fake_gem', path: '#{fake_gem_path}' - gem 'ffi' if Gem.win_platform? # Necessary for test to pass on Windows - RUBY - - let(:gemspec) { normalize_indent(<<-RUBY) } - Gem::Specification.new do |s| - s.name = 'my_fake_gem' - s.version = '1.0.0' - s.author = 'John Doe' - s.license = 'MIT' - s.homepage = 'https://example.com' - s.email = 'john.doe@example.com' - s.summary = 'A fake gem' - s.files = [File.join('lib', 'my_fake_gem.rb')] - end - RUBY - - # Specify a hook that depends on an external gem to test Gemfile loading - let(:hook) { normalize_indent(<<-RUBY) } - module Overcommit::Hook::PreCommit - class FakeHook < Base - def run - require 'my_fake_gem' - :pass + context 'given a project that uses a Gemfile' do + let(:repo_root) { File.expand_path(File.join('..', '..'), File.dirname(__FILE__)) } + let(:fake_gem_path) { File.join('lib', 'my_fake_gem') } + + # We point the overcommit gem back to this repo since we can't assume the gem + # has already been installed in a test environment + let(:gemfile) { normalize_indent(<<-RUBY) } + source 'https://rubygems.org' + + gem 'overcommit', path: '#{repo_root}' + gem 'my_fake_gem', path: '#{fake_gem_path}' + gem 'ffi' if Gem.win_platform? # Necessary for test to pass on Windows + RUBY + + let(:gemspec) { normalize_indent(<<-RUBY) } + Gem::Specification.new do |s| + s.name = 'my_fake_gem' + s.version = '1.0.0' + s.author = 'John Doe' + s.license = 'MIT' + s.homepage = 'https://example.com' + s.email = 'john.doe@example.com' + s.summary = 'A fake gem' + s.files = [File.join('lib', 'my_fake_gem.rb')] + end + RUBY + + # Specify a hook that depends on an external gem to test Gemfile loading + let(:hook) { normalize_indent(<<-RUBY) } + module Overcommit::Hook::PreCommit + class FakeHook < Base + def run + require 'my_fake_gem' + :pass + end + end + end + RUBY + + let(:config) { normalize_indent(<<-YAML) } + verify_signatures: false + + CommitMsg: + ALL: + enabled: false + + PreCommit: + ALL: + enabled: false + FakeHook: + enabled: true + requires_files: false + YAML + + around do |example| + repo do + # Since RSpec is being run within a Bundler context we need to clear it + # in order to not taint the test + Bundler.with_unbundled_env do + FileUtils.mkdir_p(File.join(fake_gem_path, 'lib')) + echo(gemspec, File.join(fake_gem_path, 'my_fake_gem.gemspec')) + touch(File.join(fake_gem_path, 'lib', 'my_fake_gem.rb')) + + echo(gemfile, '.overcommit_gems.rb') + `bundle install --gemfile=.overcommit_gems.rb` + + echo(config, '.overcommit.yml') + + # Set BUNDLE_GEMFILE so we load Overcommit from the current repo + ENV['BUNDLE_GEMFILE'] = '.overcommit_gems.rb' + `bundle exec overcommit --install > #{File::NULL}` + FileUtils.mkdir_p(File.join('.git-hooks', 'pre_commit')) + echo(hook, File.join('.git-hooks', 'pre_commit', 'fake_hook.rb')) + + Overcommit::Utils.with_environment 'OVERCOMMIT_NO_VERIFY' => '1' do + example.run + end end end end - RUBY - - let(:config) { normalize_indent(<<-YAML) } - verify_signatures: false - - CommitMsg: - ALL: - enabled: false - - PreCommit: - ALL: - enabled: false - FakeHook: - enabled: true - requires_files: false - YAML - - around do |example| - repo do - # Since RSpec is being run within a Bundler context we need to clear it - # in order to not taint the test - Bundler.with_unbundled_env do - FileUtils.mkdir_p(File.join(fake_gem_path, 'lib')) - echo(gemspec, File.join(fake_gem_path, 'my_fake_gem.gemspec')) - touch(File.join(fake_gem_path, 'lib', 'my_fake_gem.rb')) - - echo(gemfile, '.overcommit_gems.rb') - `bundle install --gemfile=.overcommit_gems.rb` + subject { shell(%w[git commit --allow-empty -m Test]) } + + context 'when configuration specifies the gemfile' do + let(:config) { "gemfile: .overcommit_gems.rb\n" + super() } + + it 'runs the hook successfully' do + subject.status.should == 0 + end + end + + context 'when configuration does not specify the gemfile' do + it 'fails to run the hook' do + subject.status.should_not == 0 + end + end + end + + context 'given a project that does not use a Gemfile' do + let(:hook) { normalize_indent(<<-RUBY) } + module Overcommit::Hook::PreCommit + class NoInvalidGemfileHook < Base + def run + if (gemfile = ENV["BUNDLE_GEMFILE"]) + raise unless File.exist?(gemfile) + end + + :pass + end + end + end + RUBY + + let(:config) { normalize_indent(<<-YAML) } + verify_signatures: false + + CommitMsg: + ALL: + enabled: false + + PreCommit: + ALL: + enabled: false + NoInvalidGemfileHook: + enabled: true + requires_files: false + YAML + + around do |example| + repo do echo(config, '.overcommit.yml') - # Set BUNDLE_GEMFILE so we load Overcommit from the current repo - ENV['BUNDLE_GEMFILE'] = '.overcommit_gems.rb' - `bundle exec overcommit --install > #{File::NULL}` + `overcommit --install > #{File::NULL}` FileUtils.mkdir_p(File.join('.git-hooks', 'pre_commit')) - echo(hook, File.join('.git-hooks', 'pre_commit', 'fake_hook.rb')) + echo(hook, File.join('.git-hooks', 'pre_commit', 'no_invalid_gemfile_hook.rb')) Overcommit::Utils.with_environment 'OVERCOMMIT_NO_VERIFY' => '1' do example.run end end end - end - - subject { shell(%w[git commit --allow-empty -m Test]) } - context 'when configuration specifies the gemfile' do - let(:config) { "gemfile: .overcommit_gems.rb\n" + super() } + subject { shell(%w[git commit --allow-empty -m Test]) } - it 'runs the hook successfully' do - subject.status.should == 0 - end - end + context 'when configuration explicitly sets the gemfile to false' do + let(:config) { "gemfile: false\n" + super() } - context 'when configuration does not specify the gemfile' do - it 'fails to run the hook' do - subject.status.should_not == 0 + it 'runs the hook successfully' do + subject.status.should == 0 + end end end end diff --git a/template-dir/hooks/commit-msg b/template-dir/hooks/commit-msg index 377c892b..87ffeb58 100755 --- a/template-dir/hooks/commit-msg +++ b/template-dir/hooks/commit-msg @@ -27,7 +27,7 @@ if hook_type == 'overcommit-hook' end # Check if Overcommit should invoke a Bundler context for loading gems -config = File.read('.overcommit.yml') =~ /gemfile: ['"]?(.*)['"]?/ +File.read('.overcommit.yml') =~ /gemfile: (?:false|['"]?(.*)['"]?)/ gemfile = Regexp.last_match(1) if gemfile diff --git a/template-dir/hooks/overcommit-hook b/template-dir/hooks/overcommit-hook index 377c892b..87ffeb58 100755 --- a/template-dir/hooks/overcommit-hook +++ b/template-dir/hooks/overcommit-hook @@ -27,7 +27,7 @@ if hook_type == 'overcommit-hook' end # Check if Overcommit should invoke a Bundler context for loading gems -config = File.read('.overcommit.yml') =~ /gemfile: ['"]?(.*)['"]?/ +File.read('.overcommit.yml') =~ /gemfile: (?:false|['"]?(.*)['"]?)/ gemfile = Regexp.last_match(1) if gemfile diff --git a/template-dir/hooks/post-checkout b/template-dir/hooks/post-checkout index 377c892b..87ffeb58 100755 --- a/template-dir/hooks/post-checkout +++ b/template-dir/hooks/post-checkout @@ -27,7 +27,7 @@ if hook_type == 'overcommit-hook' end # Check if Overcommit should invoke a Bundler context for loading gems -config = File.read('.overcommit.yml') =~ /gemfile: ['"]?(.*)['"]?/ +File.read('.overcommit.yml') =~ /gemfile: (?:false|['"]?(.*)['"]?)/ gemfile = Regexp.last_match(1) if gemfile diff --git a/template-dir/hooks/post-commit b/template-dir/hooks/post-commit index 377c892b..87ffeb58 100755 --- a/template-dir/hooks/post-commit +++ b/template-dir/hooks/post-commit @@ -27,7 +27,7 @@ if hook_type == 'overcommit-hook' end # Check if Overcommit should invoke a Bundler context for loading gems -config = File.read('.overcommit.yml') =~ /gemfile: ['"]?(.*)['"]?/ +File.read('.overcommit.yml') =~ /gemfile: (?:false|['"]?(.*)['"]?)/ gemfile = Regexp.last_match(1) if gemfile diff --git a/template-dir/hooks/post-merge b/template-dir/hooks/post-merge index 377c892b..87ffeb58 100755 --- a/template-dir/hooks/post-merge +++ b/template-dir/hooks/post-merge @@ -27,7 +27,7 @@ if hook_type == 'overcommit-hook' end # Check if Overcommit should invoke a Bundler context for loading gems -config = File.read('.overcommit.yml') =~ /gemfile: ['"]?(.*)['"]?/ +File.read('.overcommit.yml') =~ /gemfile: (?:false|['"]?(.*)['"]?)/ gemfile = Regexp.last_match(1) if gemfile diff --git a/template-dir/hooks/post-rewrite b/template-dir/hooks/post-rewrite index 377c892b..87ffeb58 100755 --- a/template-dir/hooks/post-rewrite +++ b/template-dir/hooks/post-rewrite @@ -27,7 +27,7 @@ if hook_type == 'overcommit-hook' end # Check if Overcommit should invoke a Bundler context for loading gems -config = File.read('.overcommit.yml') =~ /gemfile: ['"]?(.*)['"]?/ +File.read('.overcommit.yml') =~ /gemfile: (?:false|['"]?(.*)['"]?)/ gemfile = Regexp.last_match(1) if gemfile diff --git a/template-dir/hooks/pre-commit b/template-dir/hooks/pre-commit index 377c892b..87ffeb58 100755 --- a/template-dir/hooks/pre-commit +++ b/template-dir/hooks/pre-commit @@ -27,7 +27,7 @@ if hook_type == 'overcommit-hook' end # Check if Overcommit should invoke a Bundler context for loading gems -config = File.read('.overcommit.yml') =~ /gemfile: ['"]?(.*)['"]?/ +File.read('.overcommit.yml') =~ /gemfile: (?:false|['"]?(.*)['"]?)/ gemfile = Regexp.last_match(1) if gemfile diff --git a/template-dir/hooks/pre-push b/template-dir/hooks/pre-push index 377c892b..87ffeb58 100755 --- a/template-dir/hooks/pre-push +++ b/template-dir/hooks/pre-push @@ -27,7 +27,7 @@ if hook_type == 'overcommit-hook' end # Check if Overcommit should invoke a Bundler context for loading gems -config = File.read('.overcommit.yml') =~ /gemfile: ['"]?(.*)['"]?/ +File.read('.overcommit.yml') =~ /gemfile: (?:false|['"]?(.*)['"]?)/ gemfile = Regexp.last_match(1) if gemfile diff --git a/template-dir/hooks/pre-rebase b/template-dir/hooks/pre-rebase index 377c892b..87ffeb58 100755 --- a/template-dir/hooks/pre-rebase +++ b/template-dir/hooks/pre-rebase @@ -27,7 +27,7 @@ if hook_type == 'overcommit-hook' end # Check if Overcommit should invoke a Bundler context for loading gems -config = File.read('.overcommit.yml') =~ /gemfile: ['"]?(.*)['"]?/ +File.read('.overcommit.yml') =~ /gemfile: (?:false|['"]?(.*)['"]?)/ gemfile = Regexp.last_match(1) if gemfile diff --git a/template-dir/hooks/prepare-commit-msg b/template-dir/hooks/prepare-commit-msg index 377c892b..87ffeb58 100755 --- a/template-dir/hooks/prepare-commit-msg +++ b/template-dir/hooks/prepare-commit-msg @@ -27,7 +27,7 @@ if hook_type == 'overcommit-hook' end # Check if Overcommit should invoke a Bundler context for loading gems -config = File.read('.overcommit.yml') =~ /gemfile: ['"]?(.*)['"]?/ +File.read('.overcommit.yml') =~ /gemfile: (?:false|['"]?(.*)['"]?)/ gemfile = Regexp.last_match(1) if gemfile From 88bee0845bff4142642253f89aabaa9fd318465b Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Sun, 16 Feb 2025 13:08:25 -0800 Subject: [PATCH 50/53] Cut version 0.67.0 (#864) --- CHANGELOG.md | 4 ++++ lib/overcommit/version.rb | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d82b5b50..8b99417a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Overcommit Changelog +## 0.67.0 + +* Fix bug introduced in 0.65.0 that prevented `gemfile: false` from working correctly + ## 0.66.0 * Add `--diff` CLI option for running pre-commit hooks against only changed files diff --git a/lib/overcommit/version.rb b/lib/overcommit/version.rb index c1091e52..803dbbfc 100644 --- a/lib/overcommit/version.rb +++ b/lib/overcommit/version.rb @@ -2,5 +2,5 @@ # Defines the gem version. module Overcommit - VERSION = '0.66.0' + VERSION = '0.67.0' end From 9f142c2a4f66a63e27ae2e5c64f507fc36f3807b Mon Sep 17 00:00:00 2001 From: Pedro Fayolle Date: Thu, 20 Feb 2025 03:17:00 +0900 Subject: [PATCH 51/53] Add note about unsupported YAML features in `gemfile:` line in default.yml (#865) Related to #863 and [this comment](https://github.com/sds/overcommit/issues/862#issuecomment-2641924147): > Having a similar problem since we had this line in our `.overcommit.yml`: > > ```yaml > gemfile: Gemfile # enforce bundled version of overcommit > ``` > > And now overcommit doesn't strip out the inline comment, resulting in this weird looking error message: > > ``` > Problem loading 'Gemfile # enforce bundled version of overcommit': /path/to/project/Gemfile # enforce bundled version of overcommit not found > ``` I think adding support for comments in the `gemfile:` regexp is likely overkill and may still not be enough when the next person tries to use yet another YAML feature in that line, but perhaps this little warning would help someone else avoid tripping. --- config/default.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/config/default.yml b/config/default.yml index 70ae0b2d..ba8af533 100644 --- a/config/default.yml +++ b/config/default.yml @@ -32,6 +32,10 @@ # your repository, and then set the `gemfile` option below to the name you gave # the file. # (Generate lock file by running `bundle install --gemfile=.overcommit_gems.rb`) +# +# NOTE: the following line will be parsed by a regexp rather than a proper YAML +# parser, so avoid any values other than false or a string, and don't use inline +# comments gemfile: false # Where to store hook plugins specific to a repository. These are loaded in From 11ef06b6eb3398e5891e8d9d2698c4edf2318f1f Mon Sep 17 00:00:00 2001 From: raul Date: Mon, 3 Mar 2025 07:22:25 +0100 Subject: [PATCH 52/53] adds 'set' requirements to diff hook context. (#866) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Running `overcommit` with the `--diff` flag results in errors for version `0.67.0`. ```sh bundle exec overcommit --diff HEAD ``` It results on the following: ```ruby Running pre-commit hooks Check for case-insensitivity conflicts................[CaseConflicts] FAILED Hook raised unexpected error uninitialized constant Overcommit::Hook::PreCommit::CaseConflicts::Set repo_files = Set.new(applicable_files) ^^^ .bundle/ruby/3.1.0/gems/overcommit-0.67.0/lib/overcommit/hook/pre_commit/case_conflicts.rb:8:in `run' .bundle/ruby/3.1.0/gems/overcommit-0.67.0/lib/overcommit/hook/base.rb:47:in `block in run_and_transform' .bundle/ruby/3.1.0/gems/overcommit-0.67.0/lib/overcommit/utils.rb:260:in `with_environment' .bundle/ruby/3.1.0/gems/overcommit-0.67.0/lib/overcommit/hook/base.rb:47:in `run_and_transform' .bundle/ruby/3.1.0/gems/overcommit-0.67.0/lib/overcommit/hook_runner.rb:162:in `run_hook' .bundle/ruby/3.1.0/gems/overcommit-0.67.0/lib/overcommit/hook_runner.rb:98:in `block in consume' .bundle/ruby/3.1.0/gems/overcommit-0.67.0/lib/overcommit/hook_runner.rb:94:in `loop' .bundle/ruby/3.1.0/gems/overcommit-0.67.0/lib/overcommit/hook_runner.rb:94:in `consume' Analyze with RuboCop........................................[RuboCop] FAILED Hook raised unexpected error uninitialized constant Overcommit::GitRepo::Set lines = Set.new ^^^ .bundle/ruby/3.1.0/gems/overcommit-0.67.0/lib/overcommit/git_repo.rb:69:in `extract_modified_lines' .bundle/ruby/3.1.0/gems/overcommit-0.67.0/lib/overcommit/hook_context/diff.rb:17:in `modified_lines_in_file' /nix/store/0sj7d3r1kf95f27028j93j0sx3v6p1kw-ruby-3.1.6/lib/ruby/3.1.0/forwardable.rb:238:in `modified_lines_in_file' .bundle/ruby/3.1.0/gems/overcommit-0.67.0/lib/overcommit/message_processor.rb:145:in `message_on_modified_line?' .bundle/ruby/3.1.0/gems/overcommit-0.67.0/lib/overcommit/message_processor.rb:138:in `block in remove_ignored_messages' .bundle/ruby/3.1.0/gems/overcommit-0.67.0/lib/overcommit/message_processor.rb:138:in `select' .bundle/ruby/3.1.0/gems/overcommit-0.67.0/lib/overcommit/message_processor.rb:138:in `remove_ignored_messages' .bundle/ruby/3.1.0/gems/overcommit-0.67.0/lib/overcommit/message_processor.rb:45:in `handle_modified_lines' .bundle/ruby/3.1.0/gems/overcommit-0.67.0/lib/overcommit/message_processor.rb:39:in `hook_result' .bundle/ruby/3.1.0/gems/overcommit-0.67.0/lib/overcommit/hook/base.rb:263:in `process_hook_return_value' .bundle/ruby/3.1.0/gems/overcommit-0.67.0/lib/overcommit/hook/base.rb:48:in `run_and_transform' .bundle/ruby/3.1.0/gems/overcommit-0.67.0/lib/overcommit/hook_runner.rb:162:in `run_hook' .bundle/ruby/3.1.0/gems/overcommit-0.67.0/lib/overcommit/hook_runner.rb:98:in `block in consume' .bundle/ruby/3.1.0/gems/overcommit-0.67.0/lib/overcommit/hook_runner.rb:94:in `loop' .bundle/ruby/3.1.0/gems/overcommit-0.67.0/lib/overcommit/hook_runner.rb:94:in `consume' ✗ One or more pre-commit hooks failed ``` The problems are fixed once `set` is required in the context that the sub command is run. `run_all.rb` also requires `set` where the module is [defined](https://github.com/sds/overcommit/blob/main/lib/overcommit/hook_context/run_all.rb#L3). --- lib/overcommit/hook_context/diff.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/overcommit/hook_context/diff.rb b/lib/overcommit/hook_context/diff.rb index 0c4b97e0..3e9aa568 100644 --- a/lib/overcommit/hook_context/diff.rb +++ b/lib/overcommit/hook_context/diff.rb @@ -2,6 +2,8 @@ require 'overcommit/git_repo' +require 'set' + module Overcommit::HookContext # Simulates a pre-commit context based on the diff with another git ref. # From 46c303377c495b1455531218f195c61243a61655 Mon Sep 17 00:00:00 2001 From: Shane da Silva Date: Sun, 2 Mar 2025 22:23:44 -0800 Subject: [PATCH 53/53] Cut version 0.67.1 --- CHANGELOG.md | 4 ++++ lib/overcommit/version.rb | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b99417a..ad1cb477 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Overcommit Changelog +## 0.67.1 + +* Fix `set` gem dependency error when running with `--diff` flag + ## 0.67.0 * Fix bug introduced in 0.65.0 that prevented `gemfile: false` from working correctly diff --git a/lib/overcommit/version.rb b/lib/overcommit/version.rb index 803dbbfc..872c5327 100644 --- a/lib/overcommit/version.rb +++ b/lib/overcommit/version.rb @@ -2,5 +2,5 @@ # Defines the gem version. module Overcommit - VERSION = '0.67.0' + VERSION = '0.67.1' end