rubocop-git2 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 971494e62d00b8014fc19631734832640325d7cdda40489802c2fae1fd500004
4
- data.tar.gz: 27194c03771bd5855c83331fb25dfdd77e0e507be9f49af740a2021c5a97bcef
3
+ metadata.gz: 4b3ebd323c15d20d452fff488d6f4710bb97104acf4cddab72faaaa2421f461a
4
+ data.tar.gz: 3f502393adaf844a52f37bd9c85b5bca049c5c1fffa39bfd04391bd63ec6abac
5
5
  SHA512:
6
- metadata.gz: '009a9ab5e998a0e3e1e837ed28ad773c319f198233c6d7e447c4a09ae793af43297043441730df0b041ff17db35022ed9b6ab9f814cfdc444e1606c381a0ba8c'
7
- data.tar.gz: 2cc49969985c8ff0e9b98d51bf83a4897ef22d0acd224ac946bef250ca3d37280164d64b43f65347a2830739a532e635cd84e2f1c38708e3784008e8a73edecb
6
+ metadata.gz: a301bd97fbefb05b71880a7e927ebc48b7789f040a3dfe4e85fe4f7731e68b2fa03b44f05a760525599f345b57d23b1bc9112c85c9ad0ae948a0de5d748e8dd5
7
+ data.tar.gz: 00ec8f7a896238519a26f0c3007e65c8eedf0743d576f93cd7086e58e137615b3d9fb620e8b1c42a41bb9f87e5e9c52e243be0b82bcb0d7ae71affed6e6d2f17
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/.rubocop.yml CHANGED
@@ -1,11 +1,15 @@
1
1
  AllCops:
2
2
  NewCops: enable
3
+ SuggestExtensions: false
3
4
  TargetRubyVersion: 2.6 # really 2.4, but 2.6 is lowest supported by rubocop
4
5
 
6
+ # warning! changes here might break specs that test config evaluation.
7
+ Gemspec/RequireMFA:
8
+ Enabled: false
5
9
  Layout/DotPosition:
6
10
  Enabled: false
7
11
  Metrics/BlockLength:
8
- Exclude: ['test/**/*.rb']
12
+ Exclude: ['spec/**/*.rb']
9
13
  Style/Documentation:
10
14
  Enabled: false
11
15
  Style/FrozenStringLiteralComment:
@@ -14,6 +18,8 @@ Style/ClassAndModuleChildren:
14
18
  Enabled: false
15
19
  Style/IfUnlessModifier:
16
20
  Enabled: false
21
+ Style/Lambda:
22
+ Enabled: false
17
23
  Style/SelectByRegexp:
18
24
  Enabled: false
19
25
  Style/StringLiterals:
data/CHANGELOG.md CHANGED
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.1.5] - 2023-03-27
8
+
9
+ ### Fixed
10
+
11
+ - stop using unsafe `YAML.load` on rubocop.yml
12
+
7
13
  ## [0.1.4] - 2023-03-24
8
14
 
9
15
  First release as `rubocop-git2`.
data/Gemfile CHANGED
@@ -3,5 +3,5 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  gem 'bundler'
6
- gem 'minitest'
7
6
  gem 'rake'
7
+ gem 'rspec'
data/README.md CHANGED
@@ -9,16 +9,45 @@ RuboCop for git diff.
9
9
 
10
10
  ## Installation
11
11
 
12
- Add or install `rubocop-git2`. NOT YET RELEASED - will happen soon!
12
+ Add or install `rubocop-git2`.
13
13
 
14
14
  ## Usage
15
15
 
16
+ ### Examples
17
+
18
+ ```sh
19
+ # check unstaged changes
20
+ rubocop-git
21
+
22
+ # check staged changes
23
+ rubocop-git --staged
24
+
25
+ # positional arguments are passed as git refs to git diff, e.g.:
26
+
27
+ # check both staged and unstaged changes
28
+ rubocop-git HEAD
29
+
30
+ # check the previous commit
31
+ rubocop-git HEAD~1 HEAD
32
+
33
+ # check changes between two tags
34
+ rubocop-git v1.0.0 v1.0.1
35
+
36
+ # check all changes in a branch in github actions
37
+ bundle exec rubocop-git origin/${{ github.base_ref }}
38
+ ```
39
+
40
+ ### Options
41
+
42
+ Output of `rubocop-git --help`:
43
+
16
44
  Usage: rubocop-git [options] [[commit] commit]
17
45
  -c, --config FILE Specify configuration file
18
- -r, --require FILE Require Ruby file
19
46
  -d, --debug Display debug info
20
47
  -D, --display-cop-names Display cop names in offense messages
21
- --only COP1,COP2 Run only specific cops or departments
22
- --cached git diff --cached
23
- --staged synonym of --cached
48
+ -f, --format FORMAT Set output format (see rubocop --help)
24
49
  --hound Hound compatibility mode
50
+ --only COP1,COP2 Run only specific cops or departments
51
+ -r, --require FILE Require Ruby file
52
+ --staged Inspect staged changes
53
+ --version Display version
data/Rakefile CHANGED
@@ -1,16 +1,8 @@
1
1
  require 'bundler/gem_tasks'
2
- require 'rake/testtask'
2
+ require 'rspec/core/rake_task'
3
+ require 'rubocop/rake_task'
3
4
 
4
- task default: %i[test selftest]
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ RuboCop::RakeTask.new
5
7
 
6
- Rake::TestTask.new(:test) do |t|
7
- t.libs << 'test'
8
- t.libs << 'lib'
9
- t.test_files = FileList['test/**/*_test.rb']
10
- end
11
-
12
- desc 'Run RuboCop::Git over itself'
13
- task :selftest do
14
- require_relative 'lib/rubocop/git'
15
- RuboCop::Git::Runner.new.run(commits: ['v0.0.4'])
16
- end
8
+ task default: %i[spec rubocop]
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "rubocop-git2"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -1,76 +1,72 @@
1
1
  require_relative '../git'
2
2
  require 'optparse'
3
3
 
4
- module RuboCop
5
- module Git
6
- class CLI
7
- def run(args = ARGV)
8
- @options = Options.new
9
- parse_arguments(args)
10
- Runner.new.run(@options)
11
- end
12
-
13
- private
4
+ class RuboCop::Git::CLI
5
+ def run(args = ARGV.dup)
6
+ @options = RuboCop::Git::Options.new
7
+ parse_arguments(args)
8
+ RuboCop::Git::Runner.new.run(@options)
9
+ end
14
10
 
15
- def parse_arguments(args)
16
- @options.commits = option_parser.parse(args)
17
- rescue OptionParser::InvalidOption, Options::Invalid => ex
18
- warn "ERROR: #{ex.message}"
19
- $stderr.puts
20
- warn option_parser
21
- exit 1
22
- end
11
+ private
23
12
 
24
- def option_parser
25
- @option_parser ||= OptionParser.new do |opt|
26
- opt.banner << ' [[commit] commit]'
13
+ def parse_arguments(args)
14
+ args << '--staged' if args.delete('--cached') # support synonymous flag
15
+ @options.commits = option_parser.parse(args)
16
+ rescue OptionParser::InvalidOption, Options::Invalid => e
17
+ warn "ERROR: #{e.message}"
18
+ $stderr.puts
19
+ warn option_parser
20
+ exit 1
21
+ end
27
22
 
28
- opt.on('-c', '--config FILE',
29
- 'Specify configuration file') do |config|
30
- @options.config = config
31
- end
23
+ # rubocop:disable Metrics
24
+ def option_parser
25
+ @option_parser ||= OptionParser.new do |opt|
26
+ opt.banner << ' [[commit] commit]'
32
27
 
33
- opt.on('-r', '--require FILE',
34
- 'Require Ruby file') do |file|
35
- require file
36
- end
28
+ opt.on('-c', '--config FILE',
29
+ 'Specify configuration file') do |config|
30
+ @options.config = config
31
+ end
37
32
 
38
- opt.on('-d', '--debug', 'Display debug info') do
39
- @options.rubocop[:debug] = true
40
- end
33
+ opt.on('-d', '--debug', 'Display debug info') do
34
+ @options.rubocop[:debug] = true
35
+ end
41
36
 
42
- opt.on('-D', '--display-cop-names',
43
- 'Display cop names in offense messages') do
44
- @options.rubocop[:display_cop_names] = true
45
- end
37
+ opt.on('-D', '--display-cop-names',
38
+ 'Display cop names in offense messages') do
39
+ @options.rubocop[:display_cop_names] = true
40
+ end
46
41
 
47
- opt.on('--only COP1,COP2', Array) do |args|
48
- @options.rubocop[:only] = args
49
- end
42
+ opt.on('-f', '--format FORMAT',
43
+ 'Set output format (see rubocop --help)') do |format|
44
+ @options.format = format
45
+ end
50
46
 
51
- opt.on('--cached', 'git diff --cached') do
52
- @options.cached = true
53
- end
47
+ opt.on('--hound', 'Hound compatibility mode') do
48
+ @options.hound = true
49
+ end
54
50
 
55
- opt.on('--staged', 'synonym of --cached') do
56
- @options.cached = true
57
- end
51
+ opt.on('--only COP1,COP2', Array,
52
+ 'Run only specific cops or departments') do |args|
53
+ @options.rubocop[:only] = args
54
+ end
58
55
 
59
- opt.on('--hound', 'Hound compatibility mode') do
60
- @options.hound = true
61
- end
56
+ opt.on('-r', '--require FILE',
57
+ 'Require Ruby file') do |file|
58
+ require file
59
+ end
62
60
 
63
- opt.on('-f', '--format FORMAT',
64
- 'Choose an output formatter') do |format|
65
- @options.format = format
66
- end
61
+ opt.on('--staged', 'Inspect staged changes') do
62
+ @options.cached = true
63
+ end
67
64
 
68
- opt.on('--version', 'Display version') do
69
- puts RuboCop::Git::VERSION
70
- exit 0
71
- end
72
- end
65
+ opt.on('--version', 'Display version') do
66
+ puts RuboCop::Git::VERSION
67
+ exit 0
73
68
  end
74
69
  end
75
70
  end
71
+ # rubocop:enable Metrics
76
72
  end
@@ -1,22 +1,18 @@
1
1
  require 'shellwords'
2
2
 
3
- module RuboCop
4
- module Git
5
- # ref. https://github.com/thoughtbot/hound/blob/d2f3933/app/models/commit.rb
6
- class Commit
7
- def initialize(options)
8
- @options = options
9
- end
3
+ class RuboCop::Git::Commit
4
+ # ref. https://github.com/thoughtbot/hound/blob/d2f3933/app/models/commit.rb
5
+ def initialize(options)
6
+ @options = options
7
+ end
10
8
 
11
- def file_content(filename)
12
- if @options.cached
13
- `git show :#{filename.shellescape}`
14
- elsif @options.commit_last
15
- `git show #{@options.commit_last.shellescape}:#{filename.shellescape}`
16
- else
17
- File.read(filename)
18
- end
19
- end
9
+ def file_content(filename)
10
+ if @options.cached
11
+ `git show :#{filename.shellescape}`
12
+ elsif @options.commit_last
13
+ `git show #{@options.commit_last.shellescape}:#{filename.shellescape}`
14
+ else
15
+ File.read(filename)
20
16
  end
21
17
  end
22
18
  end
@@ -1,6 +1,5 @@
1
- module RuboCop::Git
2
1
  # c.f. https://github.com/thoughtbot/hound/blob/d2f3933/app/models/commit_file.rb
3
- class CommitFile
2
+ class RuboCop::Git::CommitFile
4
3
  def initialize(file, commit)
5
4
  @file = file
6
5
  @commit = commit
@@ -15,11 +14,9 @@ class CommitFile
15
14
  end
16
15
 
17
16
  def content
18
- @content ||= begin
19
- unless removed?
20
- @commit.file_content(filename)
21
- end
22
- end
17
+ @content ||= unless removed?
18
+ @commit.file_content(filename)
19
+ end
23
20
  end
24
21
 
25
22
  def relevant_line?(line_number)
@@ -41,7 +38,6 @@ class CommitFile
41
38
  private
42
39
 
43
40
  def patch
44
- Patch.new(@file.patch)
41
+ RuboCop::Git::Patch.new(@file.patch)
45
42
  end
46
43
  end
47
- end
@@ -1,31 +1,25 @@
1
- module RuboCop
2
- module Git
3
- class DiffParser
4
- class << self
5
- def parse(diff)
6
- new.parse(diff)
7
- end
8
- end
9
-
10
- def parse(diff)
11
- files = []
12
- in_patch = false
13
-
14
- diff.each_line do |line|
15
- case line
16
- when /^diff --git/
17
- in_patch = false
18
- when %r{^\+{3} b/(?<path>[^\t\n\r]+)}
19
- files << PseudoResource.new(Regexp.last_match[:path])
20
- when /^@@/
21
- in_patch = true
22
- end
1
+ class RuboCop::Git::DiffParser
2
+ def self.parse(diff)
3
+ new.parse(diff)
4
+ end
23
5
 
24
- files.last.patch << line if in_patch
25
- end
6
+ def parse(diff) # rubocop:disable Metrics/MethodLength
7
+ files = []
8
+ in_patch = false
26
9
 
27
- files
10
+ diff.each_line do |line|
11
+ case line
12
+ when /^diff --git/
13
+ in_patch = false
14
+ when %r{^\+{3} b/(?<path>[^\t\n\r]+)}
15
+ files << RuboCop::Git::PseudoResource.new(Regexp.last_match[:path])
16
+ when /^@@/
17
+ in_patch = true
28
18
  end
19
+
20
+ files.last.patch << line if in_patch
29
21
  end
22
+
23
+ files
30
24
  end
31
25
  end
@@ -1,5 +1,2 @@
1
- module RuboCop::Git
2
1
  # ref. https://github.com/thoughtbot/hound/blob/d2f3933/app/models/file_violation.rb
3
- class FileViolation < Struct.new(:filename, :offenses)
4
- end
5
- end
2
+ RuboCop::Git::FileViolation = Struct.new(:filename, :offenses)
@@ -1,8 +1,6 @@
1
- module RuboCop::Git
2
1
  # similar to https://github.com/thoughtbot/hound/blob/d2f3933/app/models/line.rb
3
- class Line < Struct.new(:content, :line_number, :patch_position)
4
- def ==(other_line)
5
- content == other_line.content
2
+ RuboCop::Git::Line = Struct.new(:content, :line_number, :patch_position) do
3
+ def ==(other)
4
+ content == other.content
6
5
  end
7
6
  end
8
- end
@@ -1,94 +1,93 @@
1
- module RuboCop
2
- module Git
3
- class Options
4
- class Invalid < StandardError; end
5
-
6
- HOUND_DEFAULT_CONFIG_FILE =
7
- File.expand_path('../../../../hound.yml', __FILE__)
8
-
9
- attr_accessor :config
10
- attr_reader :cached, :hound, :rubocop, :format
11
-
12
- def initialize(hash_options = nil)
13
- @config = nil
14
- @cached = false
15
- @hound = false
16
- @format = RuboCop::Formatter::ClangStyleFormatter
17
- @rubocop = {}
18
- @commits = []
19
-
20
- from_hash(hash_options) if hash_options
21
- end
22
-
23
- def cached=(cached_)
24
- if cached_ && !@commits.empty?
25
- fail Invalid, 'cached and commit cannot be specified together'
26
- end
27
- @cached = !!cached_
28
- end
29
-
30
- def hound=(hound_)
31
- @hound = !!hound_
32
- end
33
-
34
- def rubocop=(rubocop_)
35
- unless rubocop_.nil? || rubocop_.is_a?(Hash)
36
- fail Invalid, "invalid rubocop: #{rubocop_.inspect}"
37
- end
38
- @rubocop = rubocop_.to_h
39
- end
40
-
41
- def commits=(commits)
42
- unless commits.is_a?(Array) && commits.length <= 2
43
- fail Invalid, "invalid commits: #{commits.inspect}"
44
- end
45
- if !commits.empty? && cached
46
- fail Invalid, 'cached and commit cannot be specified together'
47
- end
48
- @commits = commits
49
- end
50
-
51
- def format=(format)
52
- formatters =
53
- RuboCop::Formatter::FormatterSet::BUILTIN_FORMATTERS_FOR_KEYS
54
- formatter_key = formatters.keys.find do |key|
55
- key.start_with?(format)
56
- end
57
- @format = formatters[formatter_key] if formatter_key
58
- end
59
-
60
- def config_file
61
- if hound
62
- HOUND_DEFAULT_CONFIG_FILE
63
- elsif config
64
- config
65
- elsif File.exist?(RuboCop::ConfigLoader::DOTFILE)
66
- RuboCop::ConfigLoader::DOTFILE
67
- else
68
- RuboCop::ConfigLoader::DEFAULT_FILE
69
- end
70
- end
71
-
72
- def commit_first
73
- @commits.first
74
- end
75
-
76
- def commit_last
77
- @commits.length == 1 ? false : @commits.last
78
- end
79
-
80
- private
81
-
82
- def from_hash(hash_options)
83
- hash_options = hash_options.dup
84
- %w(config cached hound rubocop commits).each do |key|
85
- value = hash_options.delete(key) || hash_options.delete(key.to_sym)
86
- public_send("#{key}=", value)
87
- end
88
- unless hash_options.empty?
89
- fail Invalid, "invalid keys: #{hash_options.keys.join(' ')}"
90
- end
91
- end
1
+ class RuboCop::Git::Options
2
+ class Invalid < StandardError; end
3
+
4
+ HOUND_DEFAULT_CONFIG_FILE =
5
+ File.expand_path('../../../hound.yml', __dir__)
6
+
7
+ attr_accessor :config
8
+ attr_reader :cached, :hound, :rubocop, :format
9
+
10
+ def initialize(hash_options = nil)
11
+ @config = nil
12
+ @cached = false
13
+ @hound = false
14
+ @format = RuboCop::Formatter::ClangStyleFormatter
15
+ @rubocop = {}
16
+ @commits = []
17
+
18
+ from_hash(hash_options) if hash_options
19
+ end
20
+
21
+ def cached=(cached_)
22
+ if cached_ && !@commits.empty?
23
+ raise Invalid, 'cached and commit cannot be specified together'
24
+ end
25
+
26
+ @cached = !!cached_
27
+ end
28
+
29
+ def hound=(hound_)
30
+ @hound = !!hound_
31
+ end
32
+
33
+ def rubocop=(rubocop_)
34
+ unless rubocop_.nil? || rubocop_.is_a?(Hash)
35
+ raise Invalid, "invalid rubocop: #{rubocop_.inspect}"
36
+ end
37
+
38
+ @rubocop = rubocop_.to_h
39
+ end
40
+
41
+ def commits=(commits)
42
+ unless commits.is_a?(Array) && commits.length <= 2
43
+ raise Invalid, "invalid commits: #{commits.inspect}"
44
+ end
45
+ if !commits.empty? && cached
46
+ raise Invalid, 'cached and commit cannot be specified together'
92
47
  end
48
+
49
+ @commits = commits
50
+ end
51
+
52
+ def format=(format)
53
+ formatters =
54
+ RuboCop::Formatter::FormatterSet::BUILTIN_FORMATTERS_FOR_KEYS
55
+ formatter_key = formatters.keys.find do |key|
56
+ key.start_with?(format)
57
+ end
58
+ @format = formatters[formatter_key] if formatter_key
59
+ end
60
+
61
+ def config_file
62
+ if hound
63
+ HOUND_DEFAULT_CONFIG_FILE
64
+ elsif config
65
+ config
66
+ elsif File.exist?(RuboCop::ConfigLoader::DOTFILE)
67
+ RuboCop::ConfigLoader::DOTFILE
68
+ else
69
+ RuboCop::ConfigLoader::DEFAULT_FILE
70
+ end
71
+ end
72
+
73
+ def commit_first
74
+ @commits.first
75
+ end
76
+
77
+ def commit_last
78
+ @commits.length == 1 ? false : @commits.last
79
+ end
80
+
81
+ private
82
+
83
+ def from_hash(hash_options)
84
+ hash_options = hash_options.dup
85
+ %w[config cached hound rubocop commits].each do |key|
86
+ value = hash_options.delete(key) || hash_options.delete(key.to_sym)
87
+ public_send("#{key}=", value)
88
+ end
89
+ return if hash_options.empty?
90
+
91
+ raise Invalid, "invalid keys: #{hash_options.keys.join(' ')}"
93
92
  end
94
93
  end
@@ -1,9 +1,8 @@
1
- module RuboCop::Git
2
1
  # copy from https://github.com/thoughtbot/hound/blob/5269fa5/app/models/patch.rb
3
- class Patch
4
- RANGE_INFORMATION_LINE = /^@@ .+\+(?<line_number>\d+),/
5
- MODIFIED_LINE = /^\+(?!\+|\+)/
6
- NOT_REMOVED_LINE = /^[^-]/
2
+ class RuboCop::Git::Patch
3
+ RANGE_INFORMATION_LINE = /^@@ .+\+(?<line_number>\d+),/.freeze
4
+ MODIFIED_LINE = /^\+(?!\+|\+)/.freeze
5
+ NOT_REMOVED_LINE = /^[^-]/.freeze
7
6
 
8
7
  def initialize(body)
9
8
  @body = body || ''
@@ -18,7 +17,7 @@ class Patch
18
17
  when RANGE_INFORMATION_LINE
19
18
  line_number = Regexp.last_match[:line_number].to_i
20
19
  when MODIFIED_LINE
21
- line = Line.new(content, line_number, patch_position)
20
+ line = RuboCop::Git::Line.new(content, line_number, patch_position)
22
21
  hash[line_number] = line
23
22
  line_number += 1
24
23
  when NOT_REMOVED_LINE
@@ -33,4 +32,3 @@ class Patch
33
32
  @body.each_line
34
33
  end
35
34
  end
36
- end
@@ -1,36 +1,33 @@
1
- module RuboCop
2
- module Git
3
- # ref. https://github.com/thoughtbot/hound/blob/d2f3933/app/models/pull_request.rb
4
- class PseudoPullRequest
5
- HOUND_CONFIG_FILE = '.hound.yml'
1
+ # ref. https://github.com/thoughtbot/hound/blob/d2f3933/app/models/pull_request.rb
2
+ class RuboCop::Git::PseudoPullRequest
3
+ HOUND_CONFIG_FILE = '.hound.yml'.freeze
6
4
 
7
- def initialize(files, options)
8
- @files = files
9
- @options = options
10
- end
5
+ def initialize(files, options)
6
+ @files = files
7
+ @options = options
8
+ end
11
9
 
12
- def pull_request_files
13
- @files.map do |file|
14
- build_commit_file(file)
15
- end
16
- end
10
+ def pull_request_files
11
+ @files.map do |file|
12
+ build_commit_file(file)
13
+ end
14
+ end
17
15
 
18
- def config
19
- return unless @options.hound
20
- File.read(HOUND_CONFIG_FILE)
21
- rescue Errno::ENOENT
22
- nil
23
- end
16
+ def config
17
+ return unless @options.hound
24
18
 
25
- private
19
+ File.read(HOUND_CONFIG_FILE)
20
+ rescue Errno::ENOENT
21
+ nil
22
+ end
26
23
 
27
- def build_commit_file(file)
28
- CommitFile.new(file, head_commit)
29
- end
24
+ private
30
25
 
31
- def head_commit
32
- @head_commit ||= Commit.new(@options)
33
- end
34
- end
26
+ def build_commit_file(file)
27
+ RuboCop::Git::CommitFile.new(file, head_commit)
28
+ end
29
+
30
+ def head_commit
31
+ @head_commit ||= RuboCop::Git::Commit.new(@options)
35
32
  end
36
33
  end
@@ -1,24 +1,20 @@
1
- module RuboCop
2
- module Git
3
- class PseudoResource
4
- attr_reader :patch, :pwd, :file_relative_path
1
+ class RuboCop::Git::PseudoResource
2
+ attr_reader :patch, :pwd, :file_relative_path
5
3
 
6
- alias filename file_relative_path
4
+ alias filename file_relative_path
7
5
 
8
- def initialize(file_relative_path, pwd = Dir.pwd)
9
- @file_relative_path = file_relative_path
10
- @pwd = pwd
11
- @patch = ''
12
- end
6
+ def initialize(file_relative_path, pwd = Dir.pwd)
7
+ @file_relative_path = file_relative_path
8
+ @pwd = pwd
9
+ @patch = ''
10
+ end
13
11
 
14
- def absolute_path
15
- filename
16
- File.join(pwd, filename)
17
- end
12
+ def absolute_path
13
+ filename
14
+ File.join(pwd, filename)
15
+ end
18
16
 
19
- def status
20
- 'modified'
21
- end
22
- end
17
+ def status
18
+ 'modified'
23
19
  end
24
20
  end
@@ -1,75 +1,73 @@
1
1
  require 'shellwords'
2
2
 
3
- module RuboCop
4
- module Git
5
- # ref. https://github.com/thoughtbot/hound/blob/d2f3933/app/services/build_runner.rb
6
- class Runner
7
- def initialize(exit_on_offence: true)
8
- @exit_on_offence = exit_on_offence
9
- end
10
-
11
- def run(options = {})
12
- options = Options.new(options) unless options.is_a?(Options)
13
-
14
- @options = options
15
- @files = DiffParser.parse(git_diff(options))
16
-
17
- display_violations($stdout)
18
-
19
- ok = violations_with_valid_offences.none?
20
- exit(1) if @exit_on_offence && !ok
21
- ok
22
- end
23
-
24
- private
25
-
26
- def violations
27
- @violations ||= style_checker.violations
28
- end
29
-
30
- def violations_with_valid_offences
31
- @violations_with_valid_offences ||= violations.select { |v| valid_offences(v).any? }
32
- end
33
-
34
- def valid_offences(violation)
35
- offenses = violation.offenses
36
- offenses = offenses.reject(&:disabled?) if offenses.first.respond_to?(:disabled?)
37
- offenses.compact.sort.freeze
38
- end
39
-
40
- def style_checker
41
- StyleChecker.new(
42
- pull_request.pull_request_files,
43
- @options.rubocop,
44
- @options.config_file,
45
- pull_request.config
46
- )
47
- end
48
-
49
- def pull_request
50
- @pull_request ||= PseudoPullRequest.new(@files, @options)
51
- end
52
-
53
- def git_diff(options)
54
- args = %w(diff --diff-filter=AMCR --find-renames --find-copies)
55
-
56
- args << '--cached' if options.cached
57
- args << options.commit_first.shellescape if options.commit_first
58
- args << options.commit_last.shellescape if options.commit_last
59
-
60
- `git #{args.join(' ')}`
61
- end
62
-
63
- def display_violations(io)
64
- formatter = @options.format.new(io)
65
- formatter.started(@files)
66
-
67
- violations.map do |violation|
68
- formatter.file_finished(violation.filename, valid_offences(violation))
69
- end
70
-
71
- formatter.finished(@files.map(&:filename).freeze)
72
- end
3
+ # ref. https://github.com/thoughtbot/hound/blob/d2f3933/app/services/build_runner.rb
4
+ class RuboCop::Git::Runner
5
+ def initialize(exit_on_offence: true)
6
+ @exit_on_offence = exit_on_offence
7
+ end
8
+
9
+ def run(options = {})
10
+ unless options.is_a?(RuboCop::Git::Options)
11
+ options = RuboCop::Git::Options.new(options)
73
12
  end
13
+
14
+ @options = options
15
+ @files = RuboCop::Git::DiffParser.parse(git_diff(options))
16
+
17
+ display_violations($stdout)
18
+
19
+ ok = violations_with_valid_offences.none?
20
+ exit(1) if @exit_on_offence && !ok
21
+ ok
22
+ end
23
+
24
+ private
25
+
26
+ def violations
27
+ @violations ||= style_checker.violations
28
+ end
29
+
30
+ def violations_with_valid_offences
31
+ @violations_with_valid_offences ||= violations.select { |v| valid_offences(v).any? }
32
+ end
33
+
34
+ def valid_offences(violation)
35
+ offenses = violation.offenses
36
+ offenses = offenses.reject(&:disabled?) if offenses.first.respond_to?(:disabled?)
37
+ offenses.compact.sort.freeze
38
+ end
39
+
40
+ def style_checker
41
+ RuboCop::Git::StyleChecker.new(
42
+ pull_request.pull_request_files,
43
+ @options.rubocop,
44
+ @options.config_file,
45
+ pull_request.config
46
+ )
47
+ end
48
+
49
+ def pull_request
50
+ @pull_request ||= RuboCop::Git::PseudoPullRequest.new(@files, @options)
51
+ end
52
+
53
+ def git_diff(options)
54
+ args = %w[diff --diff-filter=AMCR --find-renames --find-copies]
55
+
56
+ args << '--cached' if options.cached
57
+ args << options.commit_first.shellescape if options.commit_first
58
+ args << options.commit_last.shellescape if options.commit_last
59
+
60
+ `git #{args.join(' ')}`
61
+ end
62
+
63
+ def display_violations(io)
64
+ formatter = @options.format.new(io)
65
+ formatter.started(@files)
66
+
67
+ violations.map do |violation|
68
+ formatter.file_finished(violation.filename, valid_offences(violation))
69
+ end
70
+
71
+ formatter.finished(@files.map(&:filename).freeze)
74
72
  end
75
73
  end
@@ -1,6 +1,5 @@
1
- module RuboCop::Git
2
- # ref. https://github.com/thoughtbot/hound/blob/d2f3933/app/models/style_checker.rb
3
- class StyleChecker
1
+ class RuboCop::Git::StyleChecker
2
+ # ref. https://github.com/thoughtbot/hound/blob/d2f3933/app/models/style_checker.rb
4
3
  def initialize(modified_files,
5
4
  rubocop_options,
6
5
  config_file,
@@ -13,7 +12,10 @@ class StyleChecker
13
12
 
14
13
  def violations
15
14
  file_violations = @modified_files.map do |modified_file|
16
- FileViolation.new(modified_file.absolute_path, offenses(modified_file))
15
+ RuboCop::Git::FileViolation.new(
16
+ modified_file.absolute_path,
17
+ offenses(modified_file)
18
+ )
17
19
  end
18
20
 
19
21
  file_violations.select do |file_violation|
@@ -35,9 +37,10 @@ class StyleChecker
35
37
  end
36
38
 
37
39
  def style_guide
38
- @style_guide ||= StyleGuide.new(@rubocop_options,
39
- @config_file,
40
- @custom_config)
40
+ @style_guide ||= RuboCop::Git::StyleGuide.new(
41
+ @rubocop_options,
42
+ @config_file,
43
+ @custom_config
44
+ )
41
45
  end
42
46
  end
43
- end
@@ -1,10 +1,9 @@
1
- module RuboCop::Git
2
1
  # ref. https://github.com/thoughtbot/hound/blob/d2f3933/app/models/style_guide.rb
3
- class StyleGuide
4
- def initialize(rubocop_options, config_file, override_config_content = nil)
2
+ class RuboCop::Git::StyleGuide
3
+ def initialize(rubocop_options, config_file, custom_config = nil)
5
4
  @rubocop_options = rubocop_options
6
5
  @config_file = config_file
7
- @override_config_content = override_config_content
6
+ @custom_config = custom_config
8
7
  end
9
8
 
10
9
  def violations(file)
@@ -77,8 +76,8 @@ class StyleGuide
77
76
  end
78
77
 
79
78
  def override_config
80
- if @override_config_content
81
- config_content = YAML.load(@override_config_content)
79
+ if @custom_config
80
+ config_content = RuboCop::Config.load_yaml_configuration(@custom_config)
82
81
  override_config = RuboCop::Config.new(config_content, "")
83
82
  override_config.add_missing_namespaces
84
83
  override_config.make_excludes_absolute
@@ -88,4 +87,3 @@ class StyleGuide
88
87
  end
89
88
  end
90
89
  end
91
- end
@@ -1,5 +1,5 @@
1
1
  module RuboCop
2
2
  module Git
3
- VERSION = '0.1.4'.freeze
3
+ VERSION = '0.1.5'.freeze
4
4
  end
5
5
  end
data/lib/rubocop/git.rb CHANGED
@@ -1,7 +1,7 @@
1
- require_relative 'git/version'
2
1
  require 'rubocop'
3
2
 
4
3
  module RuboCop::Git
4
+ autoload :CLI, "#{__dir__}/git/cli"
5
5
  autoload :Commit, "#{__dir__}/git/commit"
6
6
  autoload :CommitFile, "#{__dir__}/git/commit_file"
7
7
  autoload :DiffParser, "#{__dir__}/git/diff_parser"
@@ -14,4 +14,5 @@ module RuboCop::Git
14
14
  autoload :Runner, "#{__dir__}/git/runner"
15
15
  autoload :StyleChecker, "#{__dir__}/git/style_checker"
16
16
  autoload :StyleGuide, "#{__dir__}/git/style_guide"
17
+ autoload :VERSION, "#{__dir__}/git/version"
17
18
  end
data/rubocop-git.gemspec CHANGED
@@ -5,14 +5,14 @@ Gem::Specification.new do |spec|
5
5
  spec.version = RuboCop::Git::VERSION
6
6
  spec.authors = ['Masaki Takeuchi', 'Janosch Müller']
7
7
  spec.email = ['janosch84@gmail.com']
8
- spec.summary = %q{RuboCop for git diff.}
9
- spec.description = %q{RuboCop for git diff.}
8
+ spec.summary = 'RuboCop for git diff.'
9
+ spec.description = 'RuboCop for git diff.'
10
10
  spec.homepage = 'https://github.com/jaynetics/rubocop-git2'
11
11
  spec.license = 'MIT'
12
12
 
13
13
  spec.files = `git ls-files -z`.split("\x0")
14
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
15
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
14
+ spec.bindir = 'exe'
15
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
16
16
  spec.require_paths = ['lib']
17
17
 
18
18
  spec.required_ruby_version = '>= 2.6.0'
@@ -0,0 +1,7 @@
1
+ describe RuboCop::Git::CLI do
2
+ it "fails with invalid options" do
3
+ expect { subject.run(["--gru\u00DF"]) }
4
+ .to output(/Usage/).to_stderr
5
+ .and raise_error(SystemExit)
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ describe RuboCop::Git::Options do
2
+ it "fails with no options" do
3
+ expect { RuboCop::Git::Options.new({}) }.to raise_error(/invalid/)
4
+ end
5
+
6
+ it "fails with unknown options" do
7
+ expect { RuboCop::Git::Options.new({ foo: 1 }) }.to raise_error(/invalid/)
8
+ end
9
+
10
+ it "can pass string hash options" do
11
+ RuboCop::Git::Options.new("rubocop" => {}, "commits" => [])
12
+ end
13
+
14
+ it "can pass symbol hash options" do
15
+ RuboCop::Git::Options.new(rubocop: {}, commits: [])
16
+ end
17
+ end
@@ -0,0 +1,52 @@
1
+ describe RuboCop::Git::Runner do
2
+ it "exits with violations" do
3
+ options = RuboCop::Git::Options.new
4
+ options.commits = ["v0.0.4", "v0.0.5"]
5
+ expect { RuboCop::Git::Runner.new.run(options) }
6
+ .to output(%r{Layout/TrailingWhitespace}).to_stdout
7
+ .and raise_error(SystemExit)
8
+ end
9
+
10
+ it "enables cops passed via --only flag" do
11
+ # WITHOUT only flag
12
+ options = RuboCop::Git::Options.new
13
+ options.commits = ["v0.0.0", "v0.0.4"]
14
+ output = capture_stdout do
15
+ res = RuboCop::Git::Runner.new(exit_on_offence: false).run(options)
16
+ expect(res).to eq false
17
+ end
18
+ # check that rubocop's default `Include:` applies
19
+ expect(output).not_to include 'bad_ruby.txt'
20
+ # check that cop disabled via rubocop.yml isn't used
21
+ expect(output).not_to include 'Style/FrozenStringLiteralComment'
22
+ # check that enabled cop is used
23
+ expect(output).to include 'Style/MutableConstant'
24
+
25
+ # WITH only flag
26
+ options.rubocop[:only] = ["Style/FrozenStringLiteralComment"]
27
+ output = capture_stdout do
28
+ res = RuboCop::Git::Runner.new(exit_on_offence: false).run(options)
29
+ expect(res).to eq false
30
+ end
31
+ # check that rubocop's default `Include:` applies
32
+ expect(output).to include 'Rakefile'
33
+ # check that passed cop is used despite being disabled in rubocop.yml
34
+ expect(output).to include 'Style/FrozenStringLiteralComment'
35
+ # check that other enabled cop isn't used
36
+ expect(output).not_to include 'Style/MutableConstant'
37
+ end
38
+
39
+ it "fails with no options" do
40
+ expect { RuboCop::Git::Runner.new.run({}) }.to raise_error(/invalid/)
41
+ end
42
+
43
+ def capture_stdout(&block)
44
+ captured_stream = StringIO.new
45
+ original_stream = $stdout
46
+ $stdout = captured_stream
47
+ block.call
48
+ captured_stream.string
49
+ ensure
50
+ $stdout = original_stream
51
+ end
52
+ end
@@ -0,0 +1 @@
1
+ require 'rubocop/git'
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-git2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masaki Takeuchi
8
8
  - Janosch Müller
9
9
  autorequire:
10
- bindir: bin
10
+ bindir: exe
11
11
  cert_chain: []
12
- date: 2023-03-24 00:00:00.000000000 Z
12
+ date: 2023-03-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rubocop
@@ -35,13 +35,16 @@ extra_rdoc_files: []
35
35
  files:
36
36
  - ".github/workflows/tests.yml"
37
37
  - ".gitignore"
38
+ - ".rspec"
38
39
  - ".rubocop.yml"
39
40
  - CHANGELOG.md
40
41
  - Gemfile
41
42
  - LICENSE.txt
42
43
  - README.md
43
44
  - Rakefile
44
- - bin/rubocop-git
45
+ - bin/console
46
+ - bin/setup
47
+ - exe/rubocop-git
45
48
  - hound.yml
46
49
  - lib/rubocop/git.rb
47
50
  - lib/rubocop/git/cli.rb
@@ -59,11 +62,11 @@ files:
59
62
  - lib/rubocop/git/style_guide.rb
60
63
  - lib/rubocop/git/version.rb
61
64
  - rubocop-git.gemspec
62
- - test/bad_ruby.txt
63
- - test/rubocop/git/cli_test.rb
64
- - test/rubocop/git/options_test.rb
65
- - test/rubocop/git/runner_test.rb
66
- - test/test_helper.rb
65
+ - spec/bad_ruby.txt
66
+ - spec/rubocop/git/cli_spec.rb
67
+ - spec/rubocop/git/options_spec.rb
68
+ - spec/rubocop/git/runner_spec.rb
69
+ - spec/spec_helper.rb
67
70
  homepage: https://github.com/jaynetics/rubocop-git2
68
71
  licenses:
69
72
  - MIT
@@ -87,9 +90,4 @@ rubygems_version: 3.4.1
87
90
  signing_key:
88
91
  specification_version: 4
89
92
  summary: RuboCop for git diff.
90
- test_files:
91
- - test/bad_ruby.txt
92
- - test/rubocop/git/cli_test.rb
93
- - test/rubocop/git/options_test.rb
94
- - test/rubocop/git/runner_test.rb
95
- - test/test_helper.rb
93
+ test_files: []
@@ -1,12 +0,0 @@
1
- require_relative '../../test_helper'
2
- require 'rubocop/git/cli'
3
-
4
- describe RuboCop::Git::CLI do
5
- it 'fail with invalid options' do
6
- _ do
7
- _out, _err = capture_io do
8
- RuboCop::Git::CLI.new.run(['--gruß'])
9
- end
10
- end.must_raise(SystemExit)
11
- end
12
- end
@@ -1,18 +0,0 @@
1
- require_relative '../../test_helper'
2
- require 'rubocop/git/options'
3
-
4
- describe RuboCop::Git::Options do
5
- it 'fail with no options' do
6
- _ do
7
- RuboCop::Git::Options.new({})
8
- end.must_raise(RuboCop::Git::Options::Invalid)
9
- end
10
-
11
- it 'can pass string hash options' do
12
- RuboCop::Git::Options.new('rubocop' => {}, 'commits' => [])
13
- end
14
-
15
- it 'can pass symbol hash options' do
16
- RuboCop::Git::Options.new(rubocop: {}, commits: [])
17
- end
18
- end
@@ -1,43 +0,0 @@
1
- require_relative '../../test_helper'
2
- require 'rubocop/git/runner'
3
-
4
- describe RuboCop::Git::Runner do
5
- it 'exit with violations' do
6
- options = RuboCop::Git::Options.new
7
- options.commits = ["v0.0.4", "v0.0.5"]
8
- _ do
9
- capture_io do
10
- RuboCop::Git::Runner.new.run(options)
11
- end
12
- end.must_raise(SystemExit)
13
- end
14
-
15
- it 'enables cops passed via --only flag' do
16
- options = RuboCop::Git::Options.new
17
- options.commits = ["v0.0.0"]
18
- out, _err = capture_io do
19
- res = RuboCop::Git::Runner.new(exit_on_offence: false).run(options)
20
- res.must_equal(false)
21
- end
22
- _(out).must_match('Style/MutableConstant')
23
- _(out).wont_match('Style/FrozenStringLiteralComment')
24
- _(out).wont_match('bad_ruby.txt') # check that default `Include:` applies
25
-
26
- options.rubocop[:only] = ['Style/FrozenStringLiteralComment']
27
- out, _err = capture_io do
28
- res = RuboCop::Git::Runner.new(exit_on_offence: false).run(options)
29
- res.must_equal(false)
30
- end
31
- _(out).wont_match('Style/MutableConstant')
32
- _(out).must_match('Style/FrozenStringLiteralComment')
33
- _(out).must_match('Rakefile') # check that default `Include:` applies
34
- end
35
-
36
- it 'fail with no options' do
37
- _ do
38
- _out, _err = capture_io do
39
- RuboCop::Git::Runner.new.run({})
40
- end
41
- end.must_raise(RuboCop::Git::Options::Invalid)
42
- end
43
- end
data/test/test_helper.rb DELETED
@@ -1,2 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'rubocop/git'
File without changes
File without changes