reviewer 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.flayignore +1 -0
- data/.github/workflows/main.yml +11 -3
- data/.gitignore +5 -0
- data/.reviewer.example.yml +27 -23
- data/.reviewer.yml +58 -5
- data/.rubocop.yml +2 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +14 -0
- data/Gemfile +0 -3
- data/Gemfile.lock +54 -29
- data/README.md +5 -50
- data/exe/fmt +1 -1
- data/exe/rvw +1 -1
- data/lib/reviewer.rb +39 -26
- data/lib/reviewer/arguments.rb +25 -9
- data/lib/reviewer/arguments/files.rb +37 -5
- data/lib/reviewer/arguments/keywords.rb +23 -9
- data/lib/reviewer/arguments/tags.rb +26 -3
- data/lib/reviewer/batch.rb +64 -0
- data/lib/reviewer/command.rb +100 -0
- data/lib/reviewer/command/string.rb +72 -0
- data/lib/reviewer/command/string/env.rb +40 -0
- data/lib/reviewer/command/string/flags.rb +40 -0
- data/lib/reviewer/command/string/verbosity.rb +51 -0
- data/lib/reviewer/command/verbosity.rb +65 -0
- data/lib/reviewer/configuration.rb +24 -4
- data/lib/reviewer/conversions.rb +27 -0
- data/lib/reviewer/guidance.rb +73 -0
- data/lib/reviewer/history.rb +38 -0
- data/lib/reviewer/keywords.rb +9 -0
- data/lib/reviewer/keywords/git.rb +14 -0
- data/lib/reviewer/keywords/git/staged.rb +48 -0
- data/lib/reviewer/loader.rb +2 -3
- data/lib/reviewer/output.rb +92 -0
- data/lib/reviewer/printer.rb +25 -0
- data/lib/reviewer/runner.rb +43 -72
- data/lib/reviewer/runner/strategies/quiet.rb +90 -0
- data/lib/reviewer/runner/strategies/verbose.rb +63 -0
- data/lib/reviewer/shell.rb +58 -0
- data/lib/reviewer/shell/result.rb +69 -0
- data/lib/reviewer/shell/timer.rb +57 -0
- data/lib/reviewer/tool.rb +109 -40
- data/lib/reviewer/tool/settings.rb +18 -32
- data/lib/reviewer/tools.rb +38 -3
- data/lib/reviewer/version.rb +1 -1
- data/reviewer.gemspec +10 -2
- metadata +143 -16
- data/lib/reviewer/arguments/keywords/git.rb +0 -16
- data/lib/reviewer/arguments/keywords/git/staged.rb +0 -64
- data/lib/reviewer/logger.rb +0 -62
- data/lib/reviewer/tool/command.rb +0 -80
- data/lib/reviewer/tool/env.rb +0 -38
- data/lib/reviewer/tool/flags.rb +0 -38
- data/lib/reviewer/tool/verbosity.rb +0 -39
data/exe/fmt
CHANGED
data/exe/rvw
CHANGED
data/lib/reviewer.rb
CHANGED
@@ -1,13 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'active_support/core_ext/string'
|
4
3
|
require 'benchmark'
|
4
|
+
require 'forwardable'
|
5
|
+
require 'logger'
|
6
|
+
|
7
|
+
require_relative 'reviewer/conversions'
|
5
8
|
|
6
9
|
require_relative 'reviewer/arguments'
|
10
|
+
require_relative 'reviewer/batch'
|
11
|
+
require_relative 'reviewer/command'
|
7
12
|
require_relative 'reviewer/configuration'
|
13
|
+
require_relative 'reviewer/guidance'
|
14
|
+
require_relative 'reviewer/history'
|
15
|
+
require_relative 'reviewer/keywords'
|
8
16
|
require_relative 'reviewer/loader'
|
9
|
-
require_relative 'reviewer/
|
17
|
+
require_relative 'reviewer/output'
|
18
|
+
require_relative 'reviewer/printer'
|
10
19
|
require_relative 'reviewer/runner'
|
20
|
+
require_relative 'reviewer/shell'
|
11
21
|
require_relative 'reviewer/tool'
|
12
22
|
require_relative 'reviewer/tools'
|
13
23
|
require_relative 'reviewer/version'
|
@@ -17,21 +27,26 @@ module Reviewer
|
|
17
27
|
class Error < StandardError; end
|
18
28
|
|
19
29
|
class << self
|
20
|
-
|
30
|
+
# Resets the loaded tools
|
31
|
+
def reset!
|
32
|
+
@tools = nil
|
33
|
+
end
|
21
34
|
|
22
35
|
# Runs the `review` command for the specified tools/files. Reviewer expects all configured
|
23
36
|
# commands that are not disabled to have an entry for the `review` command.
|
37
|
+
# @param clear_streen [boolean] clears the screen to reduce noise when true
|
24
38
|
#
|
25
39
|
# @return [void] Prints output to the console
|
26
|
-
def review
|
27
|
-
perform(:review)
|
40
|
+
def review(clear_screen: false)
|
41
|
+
perform(:review, clear_screen: clear_screen)
|
28
42
|
end
|
29
43
|
|
30
44
|
# Runs the `format` command for the specified tools/files for which it is configured.
|
45
|
+
# @param clear_streen [boolean] clears the screen to reduce noise when true
|
31
46
|
#
|
32
47
|
# @return [void] Prints output to the console
|
33
|
-
def format
|
34
|
-
perform(:format)
|
48
|
+
def format(clear_screen: false)
|
49
|
+
perform(:format, clear_screen: clear_screen)
|
35
50
|
end
|
36
51
|
|
37
52
|
# The collection of arguments that were passed via the command line.
|
@@ -52,9 +67,16 @@ module Reviewer
|
|
52
67
|
# The primary output method for Reviewer to consistently display success/failure details for a
|
53
68
|
# unique run of each tool and the collective summary when relevant.
|
54
69
|
#
|
55
|
-
# @return [Reviewer::
|
56
|
-
def
|
57
|
-
@
|
70
|
+
# @return [Reviewer::Output] prints formatted output to the console.
|
71
|
+
def output
|
72
|
+
@output ||= Output.new
|
73
|
+
end
|
74
|
+
|
75
|
+
# A file store for sharing information across runs
|
76
|
+
#
|
77
|
+
# @return [Reviewer::History] a YAML::Store (or Pstore) containing data on tools
|
78
|
+
def history
|
79
|
+
@history ||= History.new
|
58
80
|
end
|
59
81
|
|
60
82
|
# Exposes the configuration options for Reviewer.
|
@@ -86,22 +108,13 @@ module Reviewer
|
|
86
108
|
# perform(:review)
|
87
109
|
#
|
88
110
|
# @return [Hash] the exit status (in integer format) for each command run
|
89
|
-
def perform(command_type)
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
results[tool.key] = exit_status
|
97
|
-
|
98
|
-
# If a single tool fails, stop there.
|
99
|
-
break unless exit_status <= tool.max_exit_status
|
100
|
-
end
|
101
|
-
end
|
102
|
-
logger.total_time(elapsed_time)
|
103
|
-
|
104
|
-
results
|
111
|
+
def perform(command_type, clear_screen: false)
|
112
|
+
system('clear') if clear_screen
|
113
|
+
|
114
|
+
results = Batch.run(command_type, tools.current)
|
115
|
+
|
116
|
+
# Return the largest exit status
|
117
|
+
exit results.values.max
|
105
118
|
end
|
106
119
|
end
|
107
120
|
end
|
data/lib/reviewer/arguments.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'slop'
|
4
|
+
|
3
5
|
require_relative 'arguments/keywords'
|
4
6
|
require_relative 'arguments/files'
|
5
7
|
require_relative 'arguments/tags'
|
6
8
|
|
7
|
-
require 'slop'
|
8
|
-
|
9
9
|
module Reviewer
|
10
10
|
# Handles option parsing for `rvw` and `fmt` commands
|
11
11
|
#
|
@@ -21,45 +21,61 @@ module Reviewer
|
|
21
21
|
class Arguments
|
22
22
|
attr_accessor :options
|
23
23
|
|
24
|
+
attr_reader :output
|
25
|
+
|
26
|
+
# A catch all for aguments passed to reviewer via the command-line.
|
27
|
+
# @param options = ARGV [Hash] options to parse and extract the relevant values for a run
|
28
|
+
#
|
29
|
+
# @return [Reviewer::Arguments] the full collection of arguments provided via the command line
|
24
30
|
def initialize(options = ARGV)
|
31
|
+
@output = Output.new
|
25
32
|
@options = Slop.parse options do |opts|
|
26
33
|
opts.array '-f', '--files', 'a list of comma-separated files or paths', delimiter: ',', default: []
|
27
34
|
opts.array '-t', '--tags', 'a list of comma-separated tags', delimiter: ',', default: []
|
28
35
|
|
29
36
|
opts.on '-v', '--version', 'print the version' do
|
30
|
-
|
37
|
+
@output.info VERSION
|
31
38
|
exit
|
32
39
|
end
|
33
40
|
|
34
41
|
opts.on '-h', '--help', 'print the help' do
|
35
|
-
|
42
|
+
@output.info opts
|
36
43
|
exit
|
37
44
|
end
|
38
45
|
end
|
39
46
|
end
|
40
47
|
|
41
|
-
|
48
|
+
# Converts the arguments to a hash for versatility
|
49
|
+
#
|
50
|
+
# @return [Hash] The files, tags, and keywords collected from the command line options
|
51
|
+
def to_h
|
42
52
|
{
|
43
53
|
files: files.raw,
|
44
54
|
tags: tags.raw,
|
45
55
|
keywords: keywords.raw
|
46
56
|
}
|
47
57
|
end
|
58
|
+
alias inspect to_h
|
48
59
|
|
60
|
+
# The tag arguments collected from the command line via the `-t` or `--tags` flag
|
61
|
+
#
|
62
|
+
# @return [Arguments::Tags] an colelction of the tag arguments collected from the command-line
|
49
63
|
def tags
|
50
64
|
@tags ||= Arguments::Tags.new(provided: options[:tags])
|
51
65
|
end
|
52
66
|
|
67
|
+
# The file arguments collected from the command line via the `-f` or `--files` flag
|
68
|
+
#
|
69
|
+
# @return [Arguments::Files] an collection of the file arguments collected from the command-line
|
53
70
|
def files
|
54
71
|
@files ||= Arguments::Files.new(provided: options[:files])
|
55
72
|
end
|
56
73
|
|
74
|
+
# The leftover arguments collected from the command line without being associated with a flag
|
75
|
+
#
|
76
|
+
# @return [Arguments::Keywords] an collection of the leftover arguments as keywords
|
57
77
|
def keywords
|
58
78
|
@keywords ||= Arguments::Keywords.new(options.arguments)
|
59
79
|
end
|
60
|
-
|
61
|
-
def tool_names
|
62
|
-
@tool_names ||= keywords.for_tool_names.to_a
|
63
|
-
end
|
64
80
|
end
|
65
81
|
end
|
@@ -2,34 +2,58 @@
|
|
2
2
|
|
3
3
|
module Reviewer
|
4
4
|
class Arguments
|
5
|
-
# Generates
|
5
|
+
# Generates a Ruby-friendly list (Array) of files to run the command against from the provided
|
6
|
+
# command line arguments
|
6
7
|
class Files
|
7
8
|
attr_reader :provided, :keywords
|
8
9
|
|
9
10
|
alias raw provided
|
10
11
|
|
12
|
+
# Generates and instance of files from the provided arguments
|
13
|
+
# @param provided: Reviewer.arguments.files.raw [Array, String] file arguments provided
|
14
|
+
# directly via the -f or --files flag on the command line.
|
15
|
+
# @param keywords: Reviewer.arguments.keywords [Array, String] keywords that can potentially
|
16
|
+
# be translated to a list of files (ex. 'staged')
|
17
|
+
#
|
18
|
+
# @return [Arguments::Files] the container for determining targeted files from the provided
|
19
|
+
# command line arguments
|
11
20
|
def initialize(provided: Reviewer.arguments.files.raw, keywords: Reviewer.arguments.keywords)
|
12
21
|
@provided = Array(provided)
|
13
22
|
@keywords = Array(keywords)
|
14
23
|
end
|
15
24
|
|
25
|
+
# Provides the full list of file/path values derived from the command-line arguments
|
26
|
+
#
|
27
|
+
# @return [Array<String>] full collection of the file arguments as a string
|
16
28
|
def to_a
|
17
29
|
file_list
|
18
30
|
end
|
19
31
|
|
32
|
+
# Provides the full list of file/path values derived from the command-line arguments
|
33
|
+
#
|
34
|
+
# @return [String] comma-separated string of the derived tag values
|
20
35
|
def to_s
|
21
36
|
to_a.join(',')
|
22
37
|
end
|
23
38
|
|
24
|
-
|
39
|
+
# Summary of the state of the file arguments
|
40
|
+
#
|
41
|
+
# @return [Hash] represents the summary of the file values parsed from the command-line
|
42
|
+
def to_h
|
25
43
|
{
|
26
|
-
provided: provided,
|
44
|
+
provided: provided.sort,
|
27
45
|
from_keywords: from_keywords
|
28
46
|
}
|
29
47
|
end
|
48
|
+
alias inspect to_h
|
30
49
|
|
31
50
|
private
|
32
51
|
|
52
|
+
# Combines the sorted list of unique files/paths by merging the explicitly-provided file
|
53
|
+
# arguments as well as those that were translated from any relevant keyword arguments.
|
54
|
+
#
|
55
|
+
# @return [Array] full list of files/paths passed via command-line including those extracted
|
56
|
+
# as a result of a keyword argument like `staged`
|
33
57
|
def file_list
|
34
58
|
@file_list ||= [
|
35
59
|
*provided,
|
@@ -37,6 +61,10 @@ module Reviewer
|
|
37
61
|
].compact.sort.uniq
|
38
62
|
end
|
39
63
|
|
64
|
+
# Converts relevant keywords to the list of files they implicitly represent.
|
65
|
+
#
|
66
|
+
# @return [Array] list of files/paths translated from any keyword arguments that represent a
|
67
|
+
# list of files
|
40
68
|
def from_keywords
|
41
69
|
return [] unless keywords.any?
|
42
70
|
|
@@ -44,12 +72,16 @@ module Reviewer
|
|
44
72
|
next unless respond_to?(keyword.to_sym, true)
|
45
73
|
|
46
74
|
send(keyword.to_sym)
|
47
|
-
end.flatten.uniq
|
75
|
+
end.flatten.compact.uniq
|
48
76
|
end
|
49
77
|
|
78
|
+
# If `staged` is passed as a keyword via the command-line, this will get the list of staged
|
79
|
+
# files via Git
|
80
|
+
#
|
81
|
+
# @return [Array] list of the currently staged files
|
50
82
|
def staged
|
51
83
|
# Use git for list of staged fields
|
52
|
-
::Reviewer::
|
84
|
+
::Reviewer::Keywords::Git::Staged.list
|
53
85
|
end
|
54
86
|
end
|
55
87
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'keywords/git'
|
4
|
-
|
5
3
|
module Reviewer
|
6
4
|
class Arguments
|
7
5
|
# Handles interpreting all 'leftover' arguments and translating them to file-related,
|
@@ -13,19 +11,34 @@ module Reviewer
|
|
13
11
|
|
14
12
|
alias raw provided
|
15
13
|
|
14
|
+
# Generates an instace of parsed keywords from the provided arguments
|
15
|
+
# @param *provided [Array<String>] the leftover (non-flag) arguments from the command line
|
16
|
+
#
|
17
|
+
# @return [Arguments::Keywords]
|
16
18
|
def initialize(*provided)
|
17
19
|
@provided = Array(provided.flatten)
|
18
20
|
end
|
19
21
|
|
22
|
+
# Proves the full list of raw keyword arguments explicitly passed via command-line as an array
|
23
|
+
#
|
24
|
+
# @return [Array] full collection of the provided keyword arguments as a string
|
20
25
|
def to_a
|
21
26
|
provided
|
22
27
|
end
|
23
28
|
|
29
|
+
# Provides the full list of raw keyword arguments explicitly passed via command-line as a
|
30
|
+
# comma-separated string
|
31
|
+
#
|
32
|
+
# @return [String] comma-separated list of the file arguments as a string
|
24
33
|
def to_s
|
25
34
|
to_a.join(',')
|
26
35
|
end
|
27
36
|
|
28
|
-
|
37
|
+
# Summary of the state of keyword arguments based on how Reviewer parsed them
|
38
|
+
#
|
39
|
+
# @return [Hash] represents the summary of the keyword values parsed from the command-line and
|
40
|
+
# grouped based on how they were parsed
|
41
|
+
def to_h
|
29
42
|
{
|
30
43
|
provided: provided,
|
31
44
|
recognized: recognized,
|
@@ -35,6 +48,7 @@ module Reviewer
|
|
35
48
|
for_tool_names: for_tool_names
|
36
49
|
}
|
37
50
|
end
|
51
|
+
alias inspect to_h
|
38
52
|
|
39
53
|
# Extracts reserved keywords from the provided arguments
|
40
54
|
#
|
@@ -82,17 +96,17 @@ module Reviewer
|
|
82
96
|
#
|
83
97
|
# @return [Array<String>] all unique configured tags
|
84
98
|
def configured_tags
|
85
|
-
|
99
|
+
tools.enabled.map(&:tags).flatten.uniq.sort
|
86
100
|
end
|
87
101
|
|
88
102
|
# Provides the complete list of all configured tool names for enabled tools
|
89
103
|
#
|
90
|
-
# @return [Array<String>] all unique configured
|
104
|
+
# @return [Array<String>] all unique configured tools
|
91
105
|
def configured_tool_names
|
92
106
|
# We explicitly don't sort the tool names list because Reviewer uses the configuration order
|
93
107
|
# to determine the execution order. So not sorting maintains the predicted order it will run
|
94
108
|
# in and leaves the option to sort to the consuming code if needed
|
95
|
-
|
109
|
+
tools.all.map { |tool| tool.key.to_s }
|
96
110
|
end
|
97
111
|
|
98
112
|
private
|
@@ -100,8 +114,8 @@ module Reviewer
|
|
100
114
|
# Provides a collection of enabled Tools for convenient access
|
101
115
|
#
|
102
116
|
# @return [Array<Reviewer::Tool>] collection of all currently enabled tools
|
103
|
-
def
|
104
|
-
@
|
117
|
+
def tools
|
118
|
+
@tools ||= Reviewer.tools
|
105
119
|
end
|
106
120
|
|
107
121
|
# Syntactic sugar for finding intersections with valid keywords
|
@@ -109,7 +123,7 @@ module Reviewer
|
|
109
123
|
#
|
110
124
|
# @return [Array<String>] the list of intersecting values
|
111
125
|
def intersection_with(values)
|
112
|
-
values
|
126
|
+
(values & provided).uniq.sort
|
113
127
|
end
|
114
128
|
end
|
115
129
|
end
|
@@ -8,28 +8,51 @@ module Reviewer
|
|
8
8
|
|
9
9
|
alias raw provided
|
10
10
|
|
11
|
+
# Generates an instace of parsed tags from the provided arguments
|
12
|
+
# @param provided: Reviewer.arguments.tags.raw [Array<String>] tag arguments provided
|
13
|
+
# directly via the -t or --tags flag on the command line.
|
14
|
+
# @param keywords: Reviewer.arguments.keywords [Array, String] keywords that can potentially
|
15
|
+
# be translated to a list of tags based on the tags used in the configuration file
|
16
|
+
#
|
17
|
+
# @return [Arguments::Tags] the container for extracting tags from the provided command line
|
18
|
+
# arguments
|
11
19
|
def initialize(provided: Reviewer.arguments.tags.raw, keywords: Reviewer.arguments.keywords.for_tags)
|
12
20
|
@provided = Array(provided)
|
13
21
|
@keywords = Array(keywords)
|
14
22
|
end
|
15
23
|
|
24
|
+
# Provides the full list of tags values derived from the command-line arguments
|
25
|
+
#
|
26
|
+
# @return [Array<String>] full collection of the tag arguments as a string
|
16
27
|
def to_a
|
17
28
|
tag_list
|
18
29
|
end
|
19
30
|
|
31
|
+
# Provides the full list of tag values derived from the command-line arguments
|
32
|
+
#
|
33
|
+
# @return [String] comma-separated string of the derived tag values
|
20
34
|
def to_s
|
21
35
|
to_a.join(',')
|
22
36
|
end
|
23
37
|
|
24
|
-
|
38
|
+
# Summary of the state of the tag arguments
|
39
|
+
#
|
40
|
+
# @return [Hash] represents the summary of the tag values parsed from the command-line
|
41
|
+
def to_h
|
25
42
|
{
|
26
|
-
provided: provided,
|
27
|
-
from_keywords: keywords
|
43
|
+
provided: provided.sort,
|
44
|
+
from_keywords: keywords.sort
|
28
45
|
}
|
29
46
|
end
|
47
|
+
alias inspect to_h
|
30
48
|
|
31
49
|
private
|
32
50
|
|
51
|
+
# Combines the sorted list of unique tags by merging the explicitly-provided tag arguments
|
52
|
+
# as well as those that were recognized from any relevant keyword arguments.
|
53
|
+
#
|
54
|
+
# @return [Array] full list of tags passed via command-line including those matching keyword
|
55
|
+
# arguments
|
33
56
|
def tag_list
|
34
57
|
@tag_list ||= [
|
35
58
|
*provided,
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Reviewer
|
4
|
+
# Provides a structure for running commands for a given set of tools
|
5
|
+
class Batch
|
6
|
+
class UnrecognizedCommandError < ArgumentError; end
|
7
|
+
|
8
|
+
attr_reader :command_type, :tools, :output, :results
|
9
|
+
|
10
|
+
def initialize(command_type, tools, output: Reviewer.output)
|
11
|
+
@command_type = command_type
|
12
|
+
@tools = tools
|
13
|
+
@output = output
|
14
|
+
@results = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
benchmark_batch do
|
19
|
+
tools.each do |tool|
|
20
|
+
runner = Runner.new(tool, command_type, strategy)
|
21
|
+
|
22
|
+
# With multiple tools, run each one quietly.
|
23
|
+
# Otherwise, with just one tool
|
24
|
+
runner.run
|
25
|
+
|
26
|
+
# Record the exit status
|
27
|
+
capture_results(runner)
|
28
|
+
|
29
|
+
# If the tool fails, stop running other tools
|
30
|
+
break unless runner.success?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
results
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.run(*args)
|
38
|
+
new(*args).run
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def multiple_tools?
|
44
|
+
tools.size > 1
|
45
|
+
end
|
46
|
+
|
47
|
+
def strategy
|
48
|
+
multiple_tools? ? Runner::Strategies::Quiet : Runner::Strategies::Verbose
|
49
|
+
end
|
50
|
+
|
51
|
+
def capture_results(runner)
|
52
|
+
@results[runner.tool.key] = runner.exit_status
|
53
|
+
end
|
54
|
+
|
55
|
+
# Records and prints the total runtime of a block
|
56
|
+
# @param &block [type] section of code to be timed
|
57
|
+
#
|
58
|
+
# @return [void] prints the elapsed time
|
59
|
+
def benchmark_batch(&block)
|
60
|
+
elapsed_time = Benchmark.realtime(&block)
|
61
|
+
output.info "\nTotal Time ".white + "#{elapsed_time.round(1)}s".bold
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|