rubocop-gusto 10.1.1 → 10.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -0
- data/config/default.yml +18 -20
- data/config/rails.yml +4 -0
- data/lib/rubocop/cop/gusto/rspec_date_time_mock.rb +100 -0
- data/lib/rubocop/cop/gusto/use_paint_not_colorize.rb +6 -0
- data/lib/rubocop/gusto/config_yml.rb +31 -5
- data/lib/rubocop/gusto/templates/rubocop.yml +2 -2
- data/lib/rubocop/gusto/version.rb +1 -1
- metadata +12 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5b80d8e2199d3f26a7c573b61905ea30b866eb0a9f5ca2bf6eb0f6ef9891ecd4
|
|
4
|
+
data.tar.gz: 88a6fac9e262c3c40caa6ce939b194badf71a84cd05e63165b11a3f36ed4b54d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 830e8793b87b42c2a727dcbbda20a93de35f5a4887009455e8ff65bc8002dc9499d5fdfadd6971e2e5ce73660e47ddbd4cdf53eeae67c5c26d4840dadda0f092
|
|
7
|
+
data.tar.gz: 1d6b49aa37716ac6095ae0e261f8673e5c2389bff7432ba5775d39b64a86f8f17725b2f35c4c1ffbea1e32cac36751c1ee7924d6251af30b5ea7bed60466bc1c
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
## Pending
|
|
2
2
|
|
|
3
|
+
## 10.3.0
|
|
4
|
+
|
|
5
|
+
- Add Gusto/RspecDateTimeMock cop
|
|
6
|
+
|
|
7
|
+
## 10.2.0
|
|
8
|
+
|
|
9
|
+
- Fix Sorbet sigil exclusions, exclude specs from strict, and add rubocop-sorbet dependency
|
|
10
|
+
- Add ActiveSupportExtensionsEnabled to rails config
|
|
11
|
+
- Fix infinite loop and splitting problem in init command
|
|
12
|
+
- Use default Style/InverseMethods configuration
|
|
13
|
+
|
|
14
|
+
## 10.1.1
|
|
15
|
+
|
|
16
|
+
- Opt in to Rails/IgnoredColumnsAssignment
|
|
17
|
+
- Revert "Add Gusto/IgnoredColumnAssignment"
|
|
18
|
+
- Update rubocop dependency from 1.79.0 to 1.79.1
|
|
19
|
+
|
|
20
|
+
## 10.1.0
|
|
21
|
+
|
|
22
|
+
- Add Gusto/IgnoredColumnAssignment cop
|
|
23
|
+
|
|
3
24
|
## 10.0.1
|
|
4
25
|
|
|
5
26
|
- Require rubocop >= 1.76 to ensure Naming/PredicatePrefix is available.
|
data/config/default.yml
CHANGED
|
@@ -2,6 +2,7 @@ plugins:
|
|
|
2
2
|
- rubocop-rspec
|
|
3
3
|
- rubocop-performance
|
|
4
4
|
- rubocop-rake
|
|
5
|
+
- rubocop-sorbet
|
|
5
6
|
|
|
6
7
|
# After you add a rule, sort this file with `bundle exec rubocop-gusto sort config/default.yml`
|
|
7
8
|
|
|
@@ -112,6 +113,12 @@ Gusto/RegexpBypass:
|
|
|
112
113
|
- '**/spec/**/*'
|
|
113
114
|
Safe: false
|
|
114
115
|
|
|
116
|
+
Gusto/RspecDateTimeMock:
|
|
117
|
+
Description: "Don't mock Date/Time/DateTime directly. Use Rails Testing Time Helpers (eg `freeze_time` and `travel_to`) instead."
|
|
118
|
+
Include:
|
|
119
|
+
- '**/spec/**/*'
|
|
120
|
+
Safe: false
|
|
121
|
+
|
|
115
122
|
Gusto/SidekiqParams:
|
|
116
123
|
Description: 'Sidekiq perform methods cannot take keyword arguments.'
|
|
117
124
|
|
|
@@ -133,6 +140,7 @@ Gusto/ToplevelConstants:
|
|
|
133
140
|
|
|
134
141
|
Gusto/UsePaintNotColorize:
|
|
135
142
|
Description: 'Use Paint instead of colorize for terminal colors.'
|
|
143
|
+
SafeAutoCorrect: false
|
|
136
144
|
|
|
137
145
|
Gusto/VcrRecordings:
|
|
138
146
|
Description: 'VCR should be set to not record in tests. Use vcr: {record: :none}.'
|
|
@@ -339,12 +347,6 @@ RSpec/DescribeMethod:
|
|
|
339
347
|
RSpec/DescribedClass:
|
|
340
348
|
Enabled: false
|
|
341
349
|
|
|
342
|
-
RSpec/DescribedClassModuleWrapping:
|
|
343
|
-
Enabled: true
|
|
344
|
-
# TODO: improve this file matching pattern
|
|
345
|
-
Include:
|
|
346
|
-
- '**/spec/**/*_spec.rb'
|
|
347
|
-
|
|
348
350
|
RSpec/ExampleLength:
|
|
349
351
|
Enabled: false
|
|
350
352
|
|
|
@@ -426,7 +428,6 @@ Rake/ClassDefinitionInTask:
|
|
|
426
428
|
Enabled: false
|
|
427
429
|
|
|
428
430
|
Rake/Desc:
|
|
429
|
-
# TODO: Roll this out.
|
|
430
431
|
Enabled: true
|
|
431
432
|
|
|
432
433
|
Security/YAMLLoad:
|
|
@@ -443,11 +444,7 @@ Sorbet:
|
|
|
443
444
|
Sorbet/FalseSigil:
|
|
444
445
|
# We want to avoid `typed: ignore` as much as possible, as it breaks LSP tooling.
|
|
445
446
|
Include:
|
|
446
|
-
|
|
447
|
-
Exclude:
|
|
448
|
-
- bin/**/*
|
|
449
|
-
- db/**/*.rb
|
|
450
|
-
- script/**/*
|
|
447
|
+
- "**/*.{rb,rbi,rake,ru}"
|
|
451
448
|
|
|
452
449
|
Sorbet/Refinement:
|
|
453
450
|
# Still marked pending upstream, we contributed this and enable it here.
|
|
@@ -457,6 +454,13 @@ Sorbet/StrictSigil:
|
|
|
457
454
|
# Forgot the difference between typed levels? (ignore, false, true, strict, and strong)
|
|
458
455
|
# Check this out: https://sorbet.org/docs/static#file-level-granularity-strictness-levels
|
|
459
456
|
Enabled: true
|
|
457
|
+
Include:
|
|
458
|
+
- "**/*.{rb,rbi,rake,ru}"
|
|
459
|
+
Exclude:
|
|
460
|
+
- bin/**/*
|
|
461
|
+
- db/**/*.rb
|
|
462
|
+
- script/**/*
|
|
463
|
+
- spec/**/*spec.rb
|
|
460
464
|
|
|
461
465
|
Sorbet/ValidSigil:
|
|
462
466
|
Enabled: true
|
|
@@ -466,7 +470,6 @@ Sorbet/ValidSigil:
|
|
|
466
470
|
# We do suggest that the user type their file as `typed: strict`
|
|
467
471
|
SuggestedStrictness: strict
|
|
468
472
|
Exclude:
|
|
469
|
-
- '**/spec/**/*'
|
|
470
473
|
- '**/db/migrate/**/*'
|
|
471
474
|
- '**/*.{rake,arb,erb,rabl}'
|
|
472
475
|
- '**/{Gemfile,Rakefile}'
|
|
@@ -479,7 +482,6 @@ Style/Alias:
|
|
|
479
482
|
EnforcedStyle: prefer_alias_method
|
|
480
483
|
|
|
481
484
|
Style/AsciiComments:
|
|
482
|
-
# TODO: roll this out fully
|
|
483
485
|
Enabled: true
|
|
484
486
|
|
|
485
487
|
Style/AutoResourceCleanup:
|
|
@@ -542,9 +544,9 @@ Style/FrozenStringLiteralComment:
|
|
|
542
544
|
EnforcedStyle: always
|
|
543
545
|
Enabled: true
|
|
544
546
|
|
|
547
|
+
# This can make lines longer and impair readability
|
|
545
548
|
Style/GuardClause:
|
|
546
549
|
Enabled: false
|
|
547
|
-
MinBodyLength: 4
|
|
548
550
|
|
|
549
551
|
Style/HashEachMethods:
|
|
550
552
|
Enabled: true
|
|
@@ -559,7 +561,7 @@ Style/HashTransformValues:
|
|
|
559
561
|
Enabled: false
|
|
560
562
|
|
|
561
563
|
Style/IfInsideElse:
|
|
562
|
-
|
|
564
|
+
Enabled: false
|
|
563
565
|
|
|
564
566
|
Style/IfUnlessModifier:
|
|
565
567
|
Enabled: false
|
|
@@ -567,9 +569,6 @@ Style/IfUnlessModifier:
|
|
|
567
569
|
Style/ImplicitRuntimeError:
|
|
568
570
|
Enabled: false
|
|
569
571
|
|
|
570
|
-
Style/InverseMethods:
|
|
571
|
-
Enabled: false
|
|
572
|
-
|
|
573
572
|
Style/Lambda:
|
|
574
573
|
EnforcedStyle: literal
|
|
575
574
|
|
|
@@ -753,7 +752,6 @@ Style/SymbolProc:
|
|
|
753
752
|
|
|
754
753
|
Style/TernaryParentheses:
|
|
755
754
|
Enabled: false
|
|
756
|
-
EnforcedStyle: require_parentheses_when_complex
|
|
757
755
|
|
|
758
756
|
Style/TrailingCommaInArguments:
|
|
759
757
|
Enabled: true
|
data/config/rails.yml
CHANGED
|
@@ -7,6 +7,7 @@ plugins:
|
|
|
7
7
|
- rubocop-rails
|
|
8
8
|
|
|
9
9
|
AllCops:
|
|
10
|
+
ActiveSupportExtensionsEnabled: true
|
|
10
11
|
TargetRubyVersion: <%= RbConfig::CONFIG['RUBY_API_VERSION'] %>
|
|
11
12
|
MaxFilesInCache: 100000
|
|
12
13
|
Exclude:
|
|
@@ -16,6 +17,9 @@ AllCops:
|
|
|
16
17
|
- 'db/**/*schema.rb'
|
|
17
18
|
- 'db/seeds{.rb,/**/*}'
|
|
18
19
|
|
|
20
|
+
Performance/DoubleStartEndWith:
|
|
21
|
+
IncludeActiveSupportAliases: true
|
|
22
|
+
|
|
19
23
|
Rails:
|
|
20
24
|
Enabled: true
|
|
21
25
|
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# typed: false
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module RuboCop
|
|
5
|
+
module Cop
|
|
6
|
+
module Gusto
|
|
7
|
+
# Never mock time in specs. Use Rails Testing Time Helpers (eg `freeze_time` and `travel_to`) instead.
|
|
8
|
+
# .and_call_original is allowed.
|
|
9
|
+
#
|
|
10
|
+
# @example
|
|
11
|
+
# # bad
|
|
12
|
+
# context 'time specific tests' do
|
|
13
|
+
# before { allow(Time).to receive(:now).and_return(current_time) }
|
|
14
|
+
# it 'does stuff in a fixed time' do
|
|
15
|
+
# subject
|
|
16
|
+
# end
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# # good
|
|
20
|
+
# context 'time specific tests' do
|
|
21
|
+
# it 'does stuff in a fixed time' do
|
|
22
|
+
# freeze_time do
|
|
23
|
+
# subject
|
|
24
|
+
# end
|
|
25
|
+
# end
|
|
26
|
+
# end
|
|
27
|
+
class RspecDateTimeMock < Base
|
|
28
|
+
CLASSES = Set[
|
|
29
|
+
:Date,
|
|
30
|
+
:Time,
|
|
31
|
+
:DateTime
|
|
32
|
+
].freeze
|
|
33
|
+
MSG = "Don't mock #{CLASSES.join('/')} directly. Use Rails Testing Time Helpers (eg `freeze_time` and `travel_to`) instead.".freeze
|
|
34
|
+
RESTRICT_ON_SEND = %i(to).freeze
|
|
35
|
+
|
|
36
|
+
# Matches allow/expect with a time class (or chain) receiver and a `receive` or `receive_message_chain`
|
|
37
|
+
# Examples matched:
|
|
38
|
+
# allow(Time).to receive(:now)
|
|
39
|
+
# allow(Time.zone).to receive(:now)
|
|
40
|
+
# allow(Time).to receive_message_chain(:zone, :now)
|
|
41
|
+
# expect(Date.today).to receive(:wday)
|
|
42
|
+
# @!method time_mock?(node)
|
|
43
|
+
def_node_matcher :time_mock?, <<~PATTERN
|
|
44
|
+
(send
|
|
45
|
+
(send nil? {:allow :expect} #rooted_in_time_class?)
|
|
46
|
+
:to
|
|
47
|
+
{
|
|
48
|
+
(send (send nil? :receive _) ...)
|
|
49
|
+
(send (send nil? :receive_message_chain ...) ...)
|
|
50
|
+
}
|
|
51
|
+
)
|
|
52
|
+
PATTERN
|
|
53
|
+
|
|
54
|
+
def on_send(node)
|
|
55
|
+
time_mock?(node) do
|
|
56
|
+
# Allow usages that explicitly call `.and_call_original` after `receive`
|
|
57
|
+
# Example: allow(Time).to receive(:parse).and_call_original
|
|
58
|
+
receive_chain = node.first_argument
|
|
59
|
+
return if and_call_original_in_chain?(receive_chain)
|
|
60
|
+
|
|
61
|
+
add_offense(node)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
# Returns true if the given node is a const or a call chain whose root receiver
|
|
68
|
+
# is one of the protected time classes (Date/Time/DateTime)
|
|
69
|
+
def rooted_in_time_class?(node)
|
|
70
|
+
return false if node.nil?
|
|
71
|
+
|
|
72
|
+
current = node
|
|
73
|
+
while current.respond_to?(:send_type?) && current.send_type?
|
|
74
|
+
current = current.receiver
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
if current.nil?
|
|
78
|
+
return false
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
return false unless current.const_type?
|
|
82
|
+
|
|
83
|
+
# Accept both `Time` and `::Time` as root-level constants
|
|
84
|
+
namespace = current.namespace
|
|
85
|
+
is_root_level = namespace.nil? || namespace.cbase_type?
|
|
86
|
+
is_root_level && CLASSES.include?(current.children[1])
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def and_call_original_in_chain?(node)
|
|
90
|
+
return false if node.nil?
|
|
91
|
+
return false unless node.send_type?
|
|
92
|
+
|
|
93
|
+
return true if node.method?(:and_call_original)
|
|
94
|
+
|
|
95
|
+
node.each_descendant(:send).any? { |send_node| send_node.method?(:and_call_original) }
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -5,6 +5,12 @@ module RuboCop
|
|
|
5
5
|
module Gusto
|
|
6
6
|
# Requires the use of the `paint` gem for terminal color methods on strings
|
|
7
7
|
#
|
|
8
|
+
# @safety
|
|
9
|
+
# This cop's autocorrection is unsafe because it replaces colorize gem
|
|
10
|
+
# methods with Paint gem methods. If the Paint gem is not included in the
|
|
11
|
+
# project's dependencies, the corrected code will fail at runtime with a
|
|
12
|
+
# NameError (uninitialized constant Paint).
|
|
13
|
+
#
|
|
8
14
|
# @example
|
|
9
15
|
#
|
|
10
16
|
# # bad
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "pathname"
|
|
4
|
+
require "yaml"
|
|
4
5
|
|
|
5
6
|
module RuboCop
|
|
6
7
|
module Gusto
|
|
@@ -110,21 +111,46 @@ module RuboCop
|
|
|
110
111
|
# Try to find a line that exactly matches KEY_REGEX
|
|
111
112
|
# Use rstrip, not strip, to preserve indentation
|
|
112
113
|
name_line = chunk.find { |line| line.rstrip.match?(KEY_REGEX) }
|
|
113
|
-
name_line
|
|
114
|
+
if name_line
|
|
115
|
+
name_line.rstrip.delete_suffix(":")
|
|
116
|
+
else
|
|
117
|
+
# Try to find a key with value on the same line (e.g., "inherit_from: .rubocop_todo.yml")
|
|
118
|
+
first_line = chunk.find { |line| !line.strip.empty? && !line.strip.start_with?("#") }
|
|
119
|
+
if first_line&.include?(":")
|
|
120
|
+
first_line.split(":").first.strip
|
|
121
|
+
end
|
|
122
|
+
end
|
|
114
123
|
end
|
|
115
124
|
|
|
116
125
|
# Splits the lines into blocks whenever we drop from indented to unindented
|
|
117
126
|
def chunk_blocks(lines)
|
|
118
|
-
# slice whenever we drop from indented to unindented
|
|
127
|
+
# slice whenever we drop from indented to unindented line
|
|
128
|
+
# or when we encounter a new top-level key after blank line(s)
|
|
119
129
|
chunks = lines.slice_when do |prev, line|
|
|
120
|
-
|
|
130
|
+
if prev.strip.empty?
|
|
131
|
+
# split when going from blank to non-indented non-blank
|
|
132
|
+
!line.match?(INDENT_REGEX) && !line.strip.empty?
|
|
133
|
+
elsif prev.match?(INDENT_REGEX)
|
|
134
|
+
# split when going from indented to non-blank unindented
|
|
135
|
+
!line.match?(INDENT_REGEX) && !line.strip.empty?
|
|
136
|
+
else
|
|
137
|
+
# prev is non-indented, split on blank lines too
|
|
138
|
+
line.strip.empty?
|
|
139
|
+
end
|
|
121
140
|
end
|
|
122
141
|
|
|
123
142
|
# Process each chunk to remove leading newlines and add 1 trailing newline
|
|
124
143
|
chunks.filter_map do |chunk|
|
|
125
144
|
# Remove leading and trailing empty lines
|
|
126
|
-
chunk.
|
|
127
|
-
|
|
145
|
+
until chunk.empty? || !chunk.first.strip.empty?
|
|
146
|
+
chunk.shift
|
|
147
|
+
end
|
|
148
|
+
until chunk.empty? || !chunk.last.strip.empty?
|
|
149
|
+
chunk.pop
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Skip empty chunks
|
|
153
|
+
next if chunk.empty?
|
|
128
154
|
|
|
129
155
|
# Ensure each chunk ends with a blank newline
|
|
130
156
|
chunk << "\n"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rubocop-gusto
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 10.
|
|
4
|
+
version: 10.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Gusto Engineering
|
|
@@ -10,7 +10,7 @@ cert_chain: []
|
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
|
-
name:
|
|
13
|
+
name: lint_roller
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
@@ -24,35 +24,35 @@ dependencies:
|
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
25
|
version: '0'
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
|
-
name:
|
|
27
|
+
name: rubocop
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
29
29
|
requirements:
|
|
30
30
|
- - ">="
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: '
|
|
32
|
+
version: '1.76'
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
37
|
- - ">="
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: '
|
|
39
|
+
version: '1.76'
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
|
-
name: rubocop
|
|
41
|
+
name: rubocop-performance
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
|
43
43
|
requirements:
|
|
44
44
|
- - ">="
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: '
|
|
46
|
+
version: '0'
|
|
47
47
|
type: :runtime
|
|
48
48
|
prerelease: false
|
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
50
|
requirements:
|
|
51
51
|
- - ">="
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: '
|
|
53
|
+
version: '0'
|
|
54
54
|
- !ruby/object:Gem::Dependency
|
|
55
|
-
name: rubocop-
|
|
55
|
+
name: rubocop-rake
|
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
|
57
57
|
requirements:
|
|
58
58
|
- - ">="
|
|
@@ -66,7 +66,7 @@ dependencies:
|
|
|
66
66
|
- !ruby/object:Gem::Version
|
|
67
67
|
version: '0'
|
|
68
68
|
- !ruby/object:Gem::Dependency
|
|
69
|
-
name: rubocop-
|
|
69
|
+
name: rubocop-rspec
|
|
70
70
|
requirement: !ruby/object:Gem::Requirement
|
|
71
71
|
requirements:
|
|
72
72
|
- - ">="
|
|
@@ -80,7 +80,7 @@ dependencies:
|
|
|
80
80
|
- !ruby/object:Gem::Version
|
|
81
81
|
version: '0'
|
|
82
82
|
- !ruby/object:Gem::Dependency
|
|
83
|
-
name: rubocop-
|
|
83
|
+
name: rubocop-sorbet
|
|
84
84
|
requirement: !ruby/object:Gem::Requirement
|
|
85
85
|
requirements:
|
|
86
86
|
- - ">="
|
|
@@ -140,6 +140,7 @@ files:
|
|
|
140
140
|
- lib/rubocop/cop/gusto/rails_env.rb
|
|
141
141
|
- lib/rubocop/cop/gusto/rake_constants.rb
|
|
142
142
|
- lib/rubocop/cop/gusto/regexp_bypass.rb
|
|
143
|
+
- lib/rubocop/cop/gusto/rspec_date_time_mock.rb
|
|
143
144
|
- lib/rubocop/cop/gusto/sidekiq_params.rb
|
|
144
145
|
- lib/rubocop/cop/gusto/toplevel_constants.rb
|
|
145
146
|
- lib/rubocop/cop/gusto/use_paint_not_colorize.rb
|