rubocop 1.53.0 → 1.54.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/default.yml +4 -0
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +26 -3
- data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -0
- data/lib/rubocop/cop/layout/space_around_operators.rb +3 -1
- data/lib/rubocop/cop/lint/debugger.rb +8 -4
- data/lib/rubocop/cop/lint/mixed_case_range.rb +2 -0
- data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/void.rb +11 -17
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +30 -2
- data/lib/rubocop/cop/mixin/heredoc.rb +6 -2
- data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
- data/lib/rubocop/cop/style/lambda.rb +3 -3
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +1 -1
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +17 -4
- data/lib/rubocop/cop/style/yoda_condition.rb +4 -2
- data/lib/rubocop/lsp/routes.rb +8 -0
- data/lib/rubocop/lsp/runtime.rb +4 -1
- data/lib/rubocop/lsp/server.rb +6 -2
- data/lib/rubocop/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b952fc5852376637345f505d8753d44608bc082ea9bb64f9d4e61b5cc9cd6005
|
4
|
+
data.tar.gz: e7a695e76983fe1ff49d7951be70eabcb149de9bd20179f564cb61adc04d8b33
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b2f4d9249a3e283b1ed762a73c8d68b31db632de1a2e0005b99769314598fbe9394ea86a56abfff7ead03acd17d4ab343a6540ee712196bc36326959b8f9138
|
7
|
+
data.tar.gz: 1d8d0d7ac82f4440385d2b502070f3bfb872d651af0707f78ff2df6f90cd6ee51bd03ccf84c71f4f582d812a661be3af2a637895b1b0137dc37ec7606fcfcb45
|
data/README.md
CHANGED
@@ -53,7 +53,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
|
|
53
53
|
in your `Gemfile`:
|
54
54
|
|
55
55
|
```rb
|
56
|
-
gem 'rubocop', '~> 1.
|
56
|
+
gem 'rubocop', '~> 1.54', require: false
|
57
57
|
```
|
58
58
|
|
59
59
|
See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
|
data/config/default.yml
CHANGED
@@ -30,6 +30,7 @@ AllCops:
|
|
30
30
|
- '**/*.rbx'
|
31
31
|
- '**/*.ru'
|
32
32
|
- '**/*.ruby'
|
33
|
+
- '**/*.schema'
|
33
34
|
- '**/*.spec'
|
34
35
|
- '**/*.thor'
|
35
36
|
- '**/*.watchr'
|
@@ -55,6 +56,7 @@ AllCops:
|
|
55
56
|
- '**/Puppetfile'
|
56
57
|
- '**/Rakefile'
|
57
58
|
- '**/rakefile'
|
59
|
+
- '**/Schemafile'
|
58
60
|
- '**/Snapfile'
|
59
61
|
- '**/Steepfile'
|
60
62
|
- '**/Thorfile'
|
@@ -577,6 +579,8 @@ Layout/EmptyLineBetweenDefs:
|
|
577
579
|
EmptyLineBetweenMethodDefs: true
|
578
580
|
EmptyLineBetweenClassDefs: true
|
579
581
|
EmptyLineBetweenModuleDefs: true
|
582
|
+
# `DefLikeMacros` takes the name of any macro that you want to treat like a def.
|
583
|
+
DefLikeMacros: []
|
580
584
|
# `AllowAdjacentOneLineDefs` means that single line method definitions don't
|
581
585
|
# need an empty line between them. `true` by default.
|
582
586
|
AllowAdjacentOneLineDefs: true
|
@@ -135,7 +135,8 @@ module RuboCop
|
|
135
135
|
return if nodes.all?(&:single_line?) && cop_config['AllowAdjacentOneLineDefs']
|
136
136
|
|
137
137
|
correction_node = nodes.last
|
138
|
-
|
138
|
+
|
139
|
+
location = def_location(correction_node)
|
139
140
|
add_offense(location, message: message(correction_node, count: count)) do |corrector|
|
140
141
|
autocorrect(corrector, *nodes, count)
|
141
142
|
end
|
@@ -159,10 +160,28 @@ module RuboCop
|
|
159
160
|
|
160
161
|
private
|
161
162
|
|
163
|
+
def def_location(correction_node)
|
164
|
+
if correction_node.block_type?
|
165
|
+
correction_node.source_range.join(correction_node.children.first.source_range)
|
166
|
+
else
|
167
|
+
correction_node.loc.keyword.join(correction_node.loc.name)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
162
171
|
def candidate?(node)
|
163
172
|
return false unless node
|
164
173
|
|
165
|
-
method_candidate?(node) || class_candidate?(node) || module_candidate?(node)
|
174
|
+
method_candidate?(node) || class_candidate?(node) || module_candidate?(node) ||
|
175
|
+
macro_candidate?(node)
|
176
|
+
end
|
177
|
+
|
178
|
+
def empty_line_between_macros
|
179
|
+
cop_config.fetch('DefLikeMacros', []).map(&:to_sym)
|
180
|
+
end
|
181
|
+
|
182
|
+
def macro_candidate?(node)
|
183
|
+
node.block_type? && node.children.first.macro? &&
|
184
|
+
empty_line_between_macros.include?(node.children.first.method_name)
|
166
185
|
end
|
167
186
|
|
168
187
|
def method_candidate?(node)
|
@@ -226,7 +245,11 @@ module RuboCop
|
|
226
245
|
end
|
227
246
|
|
228
247
|
def def_start(node)
|
229
|
-
node.
|
248
|
+
if node.block_type? && node.children.first.send_type?
|
249
|
+
node.source_range.line
|
250
|
+
else
|
251
|
+
node.loc.keyword.line
|
252
|
+
end
|
230
253
|
end
|
231
254
|
|
232
255
|
def def_end(node)
|
@@ -153,7 +153,9 @@ module RuboCop
|
|
153
153
|
private
|
154
154
|
|
155
155
|
def regular_operator?(send_node)
|
156
|
-
|
156
|
+
return false if send_node.unary_operation? || send_node.dot? || send_node.double_colon?
|
157
|
+
|
158
|
+
operator_with_regular_syntax?(send_node)
|
157
159
|
end
|
158
160
|
|
159
161
|
def operator_with_regular_syntax?(send_node)
|
@@ -68,10 +68,7 @@ module RuboCop
|
|
68
68
|
MSG = 'Remove debugger entry point `%<source>s`.'
|
69
69
|
|
70
70
|
def on_send(node)
|
71
|
-
return
|
72
|
-
|
73
|
-
# Basically, debugger methods are not used as a method argument without arguments.
|
74
|
-
return if node.arguments.empty? && node.each_ancestor(:send, :csend).any?
|
71
|
+
return if !debugger_method?(node) || assumed_usage_context?(node)
|
75
72
|
|
76
73
|
add_offense(node)
|
77
74
|
end
|
@@ -95,6 +92,13 @@ module RuboCop
|
|
95
92
|
debugger_methods.include?(chained_method_name(send_node))
|
96
93
|
end
|
97
94
|
|
95
|
+
def assumed_usage_context?(node)
|
96
|
+
# Basically, debugger methods are not used as a method argument without arguments.
|
97
|
+
return false unless node.arguments.empty? && node.each_ancestor(:send, :csend).any?
|
98
|
+
|
99
|
+
node.each_ancestor.none?(&:lambda_or_proc?)
|
100
|
+
end
|
101
|
+
|
98
102
|
def chained_method_name(send_node)
|
99
103
|
chained_method_name = send_node.method_name.to_s
|
100
104
|
receiver = send_node.receiver
|
@@ -124,7 +124,7 @@ module RuboCop
|
|
124
124
|
source == value ||
|
125
125
|
# `Symbol#inspect` uses double quotes, but allow single-quoted
|
126
126
|
# symbols to work as well.
|
127
|
-
source.tr("'", '"') == value
|
127
|
+
source.gsub('"', '\"').tr("'", '"') == value
|
128
128
|
end
|
129
129
|
|
130
130
|
def requires_quotes?(sym_node)
|
@@ -113,9 +113,15 @@ module RuboCop
|
|
113
113
|
def check_var(node)
|
114
114
|
return unless node.variable? || node.const_type?
|
115
115
|
|
116
|
-
|
117
|
-
|
118
|
-
|
116
|
+
if node.const_type? && node.special_keyword?
|
117
|
+
add_offense(node, message: format(VAR_MSG, var: node.source)) do |corrector|
|
118
|
+
autocorrect_void_expression(corrector, node)
|
119
|
+
end
|
120
|
+
else
|
121
|
+
add_offense(node.loc.name,
|
122
|
+
message: format(VAR_MSG, var: node.loc.name.source)) do |corrector|
|
123
|
+
autocorrect_void_expression(corrector, node)
|
124
|
+
end
|
119
125
|
end
|
120
126
|
end
|
121
127
|
|
@@ -123,7 +129,7 @@ module RuboCop
|
|
123
129
|
return if !node.literal? || node.xstr_type? || node.range_type?
|
124
130
|
|
125
131
|
add_offense(node, message: format(LIT_MSG, lit: node.source)) do |corrector|
|
126
|
-
|
132
|
+
autocorrect_void_expression(corrector, node)
|
127
133
|
end
|
128
134
|
end
|
129
135
|
|
@@ -131,7 +137,7 @@ module RuboCop
|
|
131
137
|
return unless node.self_type?
|
132
138
|
|
133
139
|
add_offense(node, message: SELF_MSG) do |corrector|
|
134
|
-
|
140
|
+
autocorrect_void_expression(corrector, node)
|
135
141
|
end
|
136
142
|
end
|
137
143
|
|
@@ -181,18 +187,6 @@ module RuboCop
|
|
181
187
|
end
|
182
188
|
end
|
183
189
|
|
184
|
-
def autocorrect_void_var(corrector, node)
|
185
|
-
corrector.remove(range_with_surrounding_space(range: node.loc.name, side: :left))
|
186
|
-
end
|
187
|
-
|
188
|
-
def autocorrect_void_literal(corrector, node)
|
189
|
-
corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
|
190
|
-
end
|
191
|
-
|
192
|
-
def autocorrect_void_self(corrector, node)
|
193
|
-
corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
|
194
|
-
end
|
195
|
-
|
196
190
|
def autocorrect_void_expression(corrector, node)
|
197
191
|
corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
|
198
192
|
end
|
@@ -63,7 +63,7 @@ module RuboCop
|
|
63
63
|
types
|
64
64
|
end
|
65
65
|
|
66
|
-
def code_length(node)
|
66
|
+
def code_length(node) # rubocop:disable Metrics/MethodLength
|
67
67
|
if classlike_node?(node)
|
68
68
|
classlike_code_length(node)
|
69
69
|
elsif heredoc_node?(node)
|
@@ -72,7 +72,14 @@ module RuboCop
|
|
72
72
|
body = extract_body(node)
|
73
73
|
return 0 unless body
|
74
74
|
|
75
|
-
|
75
|
+
source =
|
76
|
+
if node_with_heredoc?(body)
|
77
|
+
source_from_node_with_heredoc(body)
|
78
|
+
else
|
79
|
+
body.source.lines
|
80
|
+
end
|
81
|
+
|
82
|
+
source.count { |line| !irrelevant_line?(line) }
|
76
83
|
end
|
77
84
|
end
|
78
85
|
|
@@ -175,6 +182,27 @@ module RuboCop
|
|
175
182
|
def another_args?(node)
|
176
183
|
node.call_type? && node.arguments.count > 1
|
177
184
|
end
|
185
|
+
|
186
|
+
def node_with_heredoc?(node)
|
187
|
+
node.each_descendant(:str, :dstr).any? { |descendant| heredoc_node?(descendant) }
|
188
|
+
end
|
189
|
+
|
190
|
+
def source_from_node_with_heredoc(node)
|
191
|
+
last_line = -1
|
192
|
+
node.each_descendant do |descendant|
|
193
|
+
next unless descendant.loc
|
194
|
+
|
195
|
+
descendant_last_line =
|
196
|
+
if heredoc_node?(descendant)
|
197
|
+
descendant.loc.heredoc_end.line
|
198
|
+
else
|
199
|
+
descendant.last_line
|
200
|
+
end
|
201
|
+
|
202
|
+
last_line = [last_line, descendant_last_line].max
|
203
|
+
end
|
204
|
+
@processed_source[(node.first_line - 1)..(last_line - 1)]
|
205
|
+
end
|
178
206
|
end
|
179
207
|
end
|
180
208
|
end
|
@@ -26,11 +26,15 @@ module RuboCop
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def delimiter_string(node)
|
29
|
-
node.source.match(OPENING_DELIMITER)
|
29
|
+
return '' unless (match = node.source.match(OPENING_DELIMITER))
|
30
|
+
|
31
|
+
match.captures[1]
|
30
32
|
end
|
31
33
|
|
32
34
|
def heredoc_type(node)
|
33
|
-
node.source.match(OPENING_DELIMITER)
|
35
|
+
return '' unless (match = node.source.match(OPENING_DELIMITER))
|
36
|
+
|
37
|
+
match.captures[0]
|
34
38
|
end
|
35
39
|
end
|
36
40
|
end
|
@@ -47,7 +47,7 @@ module RuboCop
|
|
47
47
|
def correct_elsif(node)
|
48
48
|
<<~RUBY.chop
|
49
49
|
if #{node.condition.source}
|
50
|
-
#{node.if_branch
|
50
|
+
#{node.if_branch&.source}
|
51
51
|
#{build_else_branch(node.else_branch).chop}
|
52
52
|
end
|
53
53
|
RUBY
|
@@ -56,7 +56,7 @@ module RuboCop
|
|
56
56
|
def build_else_branch(second_condition)
|
57
57
|
result = <<~RUBY
|
58
58
|
elsif #{second_condition.condition.source}
|
59
|
-
#{second_condition.if_branch
|
59
|
+
#{second_condition.if_branch&.source}
|
60
60
|
RUBY
|
61
61
|
|
62
62
|
if second_condition.else_branch
|
@@ -69,10 +69,10 @@ module RuboCop
|
|
69
69
|
return unless offending_selector?(node, selector)
|
70
70
|
|
71
71
|
add_offense(node.send_node.source_range, message: message(node, selector)) do |corrector|
|
72
|
-
if node.send_node.
|
73
|
-
autocorrect_method_to_literal(corrector, node)
|
74
|
-
else
|
72
|
+
if node.send_node.lambda_literal?
|
75
73
|
LambdaLiteralToMethodCorrector.new(node).call(corrector)
|
74
|
+
else
|
75
|
+
autocorrect_method_to_literal(corrector, node)
|
76
76
|
end
|
77
77
|
end
|
78
78
|
end
|
@@ -22,7 +22,7 @@ module RuboCop
|
|
22
22
|
|
23
23
|
def on_send(node)
|
24
24
|
return unless node.method?(:require_relative)
|
25
|
-
return unless node.first_argument.str_content
|
25
|
+
return unless node.first_argument.str_content&.start_with?(CURRENT_DIRECTORY_PATH)
|
26
26
|
return unless (index = node.first_argument.source.index(CURRENT_DIRECTORY_PATH))
|
27
27
|
|
28
28
|
begin_pos = node.first_argument.source_range.begin.begin_pos + index
|
@@ -40,7 +40,9 @@ module RuboCop
|
|
40
40
|
byteindex byterindex gsub gsub! partition rpartition scan split start_with? sub sub!
|
41
41
|
].freeze
|
42
42
|
DETERMINISTIC_REGEX = /\A(?:#{LITERAL_REGEX})+\Z/.freeze
|
43
|
-
STR_SPECIAL_CHARS = %w[
|
43
|
+
STR_SPECIAL_CHARS = %w[
|
44
|
+
\a \c \C \e \f \M \n \" \' \\\\ \t \b \f \r \u \v \x \0 \1 \2 \3 \4 \5 \6 \7
|
45
|
+
].freeze
|
44
46
|
|
45
47
|
def on_send(node)
|
46
48
|
return unless (regexp_node = node.first_argument)
|
@@ -48,9 +50,7 @@ module RuboCop
|
|
48
50
|
return if !regexp_node.regopt.children.empty? || regexp_node.content == ' '
|
49
51
|
return unless determinist_regexp?(regexp_node)
|
50
52
|
|
51
|
-
|
52
|
-
quote = new_argument.include?('"') ? "'" : '"'
|
53
|
-
prefer = "#{quote}#{new_argument}#{quote}"
|
53
|
+
prefer = preferred_argument(regexp_node)
|
54
54
|
message = format(MSG, prefer: prefer, current: regexp_node.source)
|
55
55
|
|
56
56
|
add_offense(regexp_node, message: message) do |corrector|
|
@@ -64,6 +64,19 @@ module RuboCop
|
|
64
64
|
DETERMINISTIC_REGEX.match?(regexp_node.source)
|
65
65
|
end
|
66
66
|
|
67
|
+
def preferred_argument(regexp_node)
|
68
|
+
new_argument = replacement(regexp_node)
|
69
|
+
|
70
|
+
if new_argument.include?('"')
|
71
|
+
new_argument.gsub!("'", "\\\\'")
|
72
|
+
quote = "'"
|
73
|
+
else
|
74
|
+
quote = '"'
|
75
|
+
end
|
76
|
+
|
77
|
+
"#{quote}#{new_argument}#{quote}"
|
78
|
+
end
|
79
|
+
|
67
80
|
def replacement(regexp_node)
|
68
81
|
regexp_content = regexp_node.content
|
69
82
|
stack = []
|
@@ -118,16 +118,18 @@ module RuboCop
|
|
118
118
|
node.comparison_method? && !noncommutative_operator?(node)
|
119
119
|
end
|
120
120
|
|
121
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
121
122
|
def valid_yoda?(node)
|
122
|
-
|
123
|
-
rhs = node.first_argument
|
123
|
+
return true unless (rhs = node.first_argument)
|
124
124
|
|
125
|
+
lhs = node.receiver
|
125
126
|
return true if (constant_portion?(lhs) && constant_portion?(rhs)) ||
|
126
127
|
(!constant_portion?(lhs) && !constant_portion?(rhs)) ||
|
127
128
|
interpolation?(lhs)
|
128
129
|
|
129
130
|
enforce_yoda? ? constant_portion?(lhs) : constant_portion?(rhs)
|
130
131
|
end
|
132
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
131
133
|
|
132
134
|
def message(node)
|
133
135
|
format(MSG, source: node.source)
|
data/lib/rubocop/lsp/routes.rb
CHANGED
@@ -36,6 +36,8 @@ module RuboCop
|
|
36
36
|
end
|
37
37
|
|
38
38
|
handle 'initialize' do |request|
|
39
|
+
@server.configure(safe_autocorrect: safe_autocorrect?(request))
|
40
|
+
|
39
41
|
@server.write(
|
40
42
|
id: request[:id],
|
41
43
|
result: LanguageServer::Protocol::Interface::InitializeResult.new(
|
@@ -162,6 +164,12 @@ module RuboCop
|
|
162
164
|
|
163
165
|
private
|
164
166
|
|
167
|
+
def safe_autocorrect?(request)
|
168
|
+
safe_autocorrect = request.dig(:params, :initializationOptions, :safeAutocorrect)
|
169
|
+
|
170
|
+
safe_autocorrect.nil? || safe_autocorrect == true
|
171
|
+
end
|
172
|
+
|
165
173
|
def format_file(file_uri)
|
166
174
|
unless (text = @text_cache[file_uri])
|
167
175
|
Logger.log("Format request arrived before text synchronized; skipping: `#{file_uri}'")
|
data/lib/rubocop/lsp/runtime.rb
CHANGED
@@ -14,9 +14,12 @@ module RuboCop
|
|
14
14
|
# Runtime for Language Server Protocol of RuboCop.
|
15
15
|
# @api private
|
16
16
|
class Runtime
|
17
|
+
attr_writer :safe_autocorrect
|
18
|
+
|
17
19
|
def initialize(config_store)
|
18
20
|
@config_store = config_store
|
19
21
|
@logged_paths = []
|
22
|
+
@safe_autocorrect = true
|
20
23
|
end
|
21
24
|
|
22
25
|
# This abuses the `--stdin` option of rubocop and reads the formatted text
|
@@ -32,7 +35,7 @@ module RuboCop
|
|
32
35
|
# https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/runner.rb#L72
|
33
36
|
def format(path, text)
|
34
37
|
formatting_options = {
|
35
|
-
stdin: text, force_exclusion: true, autocorrect: true, safe_autocorrect:
|
38
|
+
stdin: text, force_exclusion: true, autocorrect: true, safe_autocorrect: @safe_autocorrect
|
36
39
|
}
|
37
40
|
|
38
41
|
redirect_stdout { run_rubocop(formatting_options, path) }
|
data/lib/rubocop/lsp/server.rb
CHANGED
@@ -36,8 +36,8 @@ module RuboCop
|
|
36
36
|
@routes.handle_unsupported_method(request)
|
37
37
|
end
|
38
38
|
rescue StandardError => e
|
39
|
-
log("Error #{e.class} #{e.message[0..100]}")
|
40
|
-
log(e.backtrace.inspect)
|
39
|
+
Logger.log("Error #{e.class} #{e.message[0..100]}")
|
40
|
+
Logger.log(e.backtrace.inspect)
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
@@ -53,6 +53,10 @@ module RuboCop
|
|
53
53
|
@runtime.offenses(path, text)
|
54
54
|
end
|
55
55
|
|
56
|
+
def configure(safe_autocorrect: true)
|
57
|
+
@runtime.safe_autocorrect = safe_autocorrect
|
58
|
+
end
|
59
|
+
|
56
60
|
def stop(&block)
|
57
61
|
at_exit(&block) if block
|
58
62
|
exit
|
data/lib/rubocop/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.54.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bozhidar Batsov
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date: 2023-
|
13
|
+
date: 2023-07-01 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: json
|
@@ -1023,7 +1023,7 @@ metadata:
|
|
1023
1023
|
homepage_uri: https://rubocop.org/
|
1024
1024
|
changelog_uri: https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md
|
1025
1025
|
source_code_uri: https://github.com/rubocop/rubocop/
|
1026
|
-
documentation_uri: https://docs.rubocop.org/rubocop/1.
|
1026
|
+
documentation_uri: https://docs.rubocop.org/rubocop/1.54/
|
1027
1027
|
bug_tracker_uri: https://github.com/rubocop/rubocop/issues
|
1028
1028
|
rubygems_mfa_required: 'true'
|
1029
1029
|
post_install_message:
|