goodcheck 1.6.0 → 1.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bbd50cb641f78725c89b7543fad72cc682f89212
4
- data.tar.gz: 3bfa5512cdd20c4401e6ebfbb25d32e471bb1bbe
3
+ metadata.gz: 941c25a76e1e8d433dabf11a05e9881251666ea6
4
+ data.tar.gz: af4c6b7a6f0c7de3318efd540a9031127a6eab22
5
5
  SHA512:
6
- metadata.gz: 9c9f1ae3060429088686d073c579e24b675c0e4e03461e9ccdc8b7b230e9f1c09f2f78c471cc7fe2f233ae58bc5d21fc6caadfdd94bd75b44529bc248a8abbe9
7
- data.tar.gz: 860f1810b61143bb3f3a7a09fff042919c8e82876e9c4cfb5e0f2131f4993d36d324b3a64aa20493dca3497e56e671300cb26a33ba6848672d6ffec06eca7c21
6
+ metadata.gz: 30d772081204a902869971bded0ba16b779500d3cad31a0857b75a10979c0cacbe7ce5be45b6b4c0520bd587649394bb54cf0873ea18dccba1896cedcdd20a5a
7
+ data.tar.gz: a3020566b156d0a23f3ca4b1a2ac590d39182bf47597dcc6fb89bcd861198821f671967925fcf37e0e56f01c39a388e45d9237181f2d2bb4a9b1467083c2d156
@@ -2,6 +2,11 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.7.0 (2019-05-28)
6
+
7
+ * Support a rule without `pattern` [#52](https://github.com/sider/goodcheck/pull/52)
8
+ * Let each `pattern` have `glob` [#50](https://github.com/sider/goodcheck/pull/50)
9
+
5
10
  ## 1.6.0 (2019-05-08)
6
11
 
7
12
  * Add `not` pattern rule [#49](https://github.com/sider/goodcheck/pull/49)
data/README.md CHANGED
@@ -63,7 +63,7 @@ rules:
63
63
  The *rule* hash contains the following keys.
64
64
 
65
65
  * `id`: a string to identify rules (required)
66
- * `pattern`: a *pattern* or a sequence of *pattern*s (required)
66
+ * `pattern`: a *pattern* or a sequence of *pattern*s
67
67
  * `message`: a string to tell writers why the code piece should be revised (required)
68
68
  * `justification`: a sequence of strings to tell writers when a exception can be allowed (optional)
69
69
  * `glob`: a *glob* or a sequence of *glob*s (optional)
@@ -84,11 +84,13 @@ id: com.sample.GitHub
84
84
  pattern:
85
85
  literal: Github
86
86
  case_sensitive: true
87
+ glob: []
87
88
  message: Write GitHub, not Github
88
89
  ```
89
90
 
90
91
  All regexp meta characters included in the `literal` value will be escaped.
91
92
  `case_sensitive` is an optional key and the default is `true`.
93
+ `glob` is an optional key and the default is empty.
92
94
 
93
95
  #### *regexp pattern*
94
96
 
@@ -100,12 +102,13 @@ pattern:
100
102
  regexp: \d{4,}
101
103
  case_sensitive: false
102
104
  multiline: false
105
+ glob: []
103
106
  message: Insert delimiters when writing large numbers
104
107
  justification:
105
108
  - When you are not writing numbers, including phone numbers, zip code, ...
106
109
  ```
107
110
 
108
- It accepts two optional attributes, `case_sensitive` and `multiline`.
111
+ It accepts two optional attributes, `case_sensitive`, `multiline`, and `glob`.
109
112
  The default values of `case_sensitive` and `multiline` are `true` and `false` respectively.
110
113
 
111
114
  The regexp will be passed to `Regexp.compile`.
@@ -120,6 +123,7 @@ id: com.sample.no-blink
120
123
  pattern:
121
124
  token: "<blink"
122
125
  case_sensitive: false
126
+ glob: []
123
127
  message: Stop using <blink> tag
124
128
  glob: "**/*.html"
125
129
  justification:
@@ -133,7 +137,7 @@ In that case, try using *regexp pattern*.
133
137
  The generated regexp of `<blink` is `<\s*blink\b/m`.
134
138
  It matches with `<blink />` and `< BLINK>`, but does not match with `https://www.chromium.org/blink`.
135
139
 
136
- It accepts one optional attribute, `case_sensitive`.
140
+ It accepts one optional attributes, `case_sensitive` and `glob`.
137
141
  The default value of `case_sensitive` is `true`.
138
142
  Note that the generated regexp is in multiline mode.
139
143
 
@@ -156,6 +160,54 @@ If you write a string as a `glob`, the string value can be the `pattern` of the
156
160
 
157
161
  If you omit `glob` attribute in a rule, the rule will be applied to all files given to `goodcheck`.
158
162
 
163
+ If both of your rule and its pattern has `glob`, Goodcheck will scan the pattern from the `glob` files in the pattern.
164
+
165
+ ```yaml
166
+ rules:
167
+ - id: glob_test
168
+ pattern:
169
+ - literal: 123 # This pattern applies to .css files
170
+ glob: "*.css"
171
+ - literal: abc # This pattern applies to .txt files
172
+ glob: "*.txt"
173
+ ```
174
+
175
+ ### A rule without _negated_ pattern
176
+
177
+ Goodcheck rules are usually to detect _something is included in a file_.
178
+ You can define the _negated_ rules for the opposite, _something is missing in a file_.
179
+
180
+ ```yaml
181
+ rules:
182
+ - id: negated
183
+ not:
184
+ pattern:
185
+ <!DOCTYPE html>
186
+ message: Write a doctype on HTML files.
187
+ glob: "**/*.html"
188
+ ```
189
+
190
+ ### A rule without `pattern`
191
+
192
+ You can define a rule without `pattern`.
193
+ The rule emits a issue on each file specified with `glob`.
194
+ You cannot omit `glob` from a rule definition without `pattern`.
195
+
196
+ ```yaml
197
+ rules:
198
+ - id: without_pattern
199
+ message: |
200
+ Read the operation manual for DB migration: https://example.com/guides/123
201
+ glob: db/schema.rb
202
+ ```
203
+
204
+ The output will be something like:
205
+
206
+ ```
207
+ $ goodcheck check
208
+ db/schema.rb:-:# This file is auto-generated from the current state of the database. Instead: Read the operation manual for DB migration: https://example.com/guides/123
209
+ ```
210
+
159
211
  ## Importing rules
160
212
 
161
213
  `goodcheck.yml` can have optional `import` attribute.
@@ -25,9 +25,10 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency "bundler", ">= 1.16"
26
26
  spec.add_development_dependency "rake", "~> 10.0"
27
27
  spec.add_development_dependency "minitest", "~> 5.0"
28
+ spec.add_development_dependency "minitest-reporters", "~> 1.3.6"
28
29
 
29
30
  spec.add_runtime_dependency "activesupport", ">= 4.0", "< 6.0"
30
- spec.add_runtime_dependency "strong_json", "~> 0.7.1"
31
+ spec.add_runtime_dependency "strong_json", "~> 1.0.0"
31
32
  spec.add_runtime_dependency "rainbow", "~> 3.0.0"
32
33
  spec.add_runtime_dependency "httpclient", "~> 2.8.3"
33
34
  end
@@ -8,30 +8,55 @@ module Goodcheck
8
8
  @buffer = buffer
9
9
  end
10
10
 
11
+ def use_all_patterns!
12
+ @use_all_patterns = true
13
+ end
14
+
15
+ def patterns
16
+ if @use_all_patterns
17
+ rule.patterns
18
+ else
19
+ rule.patterns.select do |pattern|
20
+ case
21
+ when pattern.globs.empty? && rule.globs.empty?
22
+ true
23
+ when pattern.globs.empty?
24
+ rule.globs.any? {|glob| glob.test(buffer.path) }
25
+ else
26
+ pattern.globs.any? {|glob| glob.test(buffer.path) }
27
+ end
28
+ end
29
+ end
30
+ end
31
+
11
32
  def scan(&block)
12
33
  if block_given?
13
- regexp = Regexp.union(*rule.patterns.map(&:regexp))
34
+ if rule.patterns.empty?
35
+ yield Issue.new(buffer: buffer, range: nil, rule: rule, text: nil)
36
+ else
37
+ regexp = Regexp.union(*patterns.map(&:regexp))
14
38
 
15
- unless rule.negated?
16
- issues = []
39
+ unless rule.negated?
40
+ issues = []
17
41
 
18
- scanner = StringScanner.new(buffer.content)
42
+ scanner = StringScanner.new(buffer.content)
19
43
 
20
- while true
21
- case
22
- when scanner.scan_until(regexp)
23
- text = scanner.matched
24
- range = (scanner.pos - text.bytesize) .. scanner.pos
25
- issues << Issue.new(buffer: buffer, range: range, rule: rule, text: text)
26
- else
27
- break
44
+ while true
45
+ case
46
+ when scanner.scan_until(regexp)
47
+ text = scanner.matched
48
+ range = (scanner.pos - text.bytesize) .. scanner.pos
49
+ issues << Issue.new(buffer: buffer, range: range, rule: rule, text: text)
50
+ else
51
+ break
52
+ end
28
53
  end
29
- end
30
54
 
31
- issues.each(&block)
32
- else
33
- unless regexp =~ buffer.content
34
- yield Issue.new(buffer: buffer, range: nil, rule: rule, text: text)
55
+ issues.each(&block)
56
+ else
57
+ unless regexp =~ buffer.content
58
+ yield Issue.new(buffer: buffer, range: nil, rule: rule, text: nil)
59
+ end
35
60
  end
36
61
  end
37
62
  else
@@ -45,8 +45,10 @@ module Goodcheck
45
45
  stderr.puts " #{trace_loc}"
46
46
  end
47
47
  1
48
- rescue StrongJSON::Type::Error => exn
49
- stderr.puts "Invalid config at #{exn.path.map {|x| "[#{x}]" }.join}"
48
+ rescue StrongJSON::Type::TypeError, StrongJSON::Type::UnexpectedAttributeError => exn
49
+ stderr.puts "Invalid config: #{exn.message}"
50
+ stderr.puts StrongJSON::ErrorReporter.new(path: exn.path).to_s
51
+
50
52
  1
51
53
  rescue Errno::ENOENT => exn
52
54
  stderr.puts "#{exn}"
@@ -3,7 +3,8 @@ module Goodcheck
3
3
  class Init
4
4
  CONFIG = <<-EOC
5
5
  rules:
6
- - id: com.example.1
6
+ # id, pattern, message are required attributes.
7
+ - id: example.github
7
8
  pattern: Github
8
9
  message: Do you want to write GitHub?
9
10
  glob:
@@ -15,9 +16,46 @@ rules:
15
16
  pass:
16
17
  - Signup via GitHub
17
18
 
18
- exclude:
19
- - node_modules
20
- - vendor
19
+ # You can have *justification* to explain the exceptional cases.
20
+ - id: example.localStorage
21
+ pattern:
22
+ token: localStorage
23
+ message: |
24
+ Using localStorage may raise error (example: with Safari in private mode)
25
+ justification:
26
+ - If you catch the errors.
27
+ - When you implement admin console, where end users won't access.
28
+ glob:
29
+ - "**/*.js"
30
+ fail:
31
+ - |
32
+ localStorage.setItem(key, value);
33
+
34
+ # You can put `not` pattern to detect something is missing.
35
+ - id: example.strict-mode
36
+ not:
37
+ pattern: use strict
38
+ message: Use *strict mode* if possible.
39
+ glob: "**/*.js"
40
+ fail:
41
+ - |
42
+ const var = "This is *sloppy* mode."
43
+
44
+ # You can omit pattern, which prints the message on the files specified by glob.
45
+ - id: example.package-lock.json
46
+ message: Some of the packages are updated!
47
+ justification:
48
+ - If you update some of the packages.
49
+ glob: "package-lock.json"
50
+
51
+ # You can import rules.
52
+ # import:
53
+ # - https://example.com/example-rules.yml
54
+
55
+ # You can skip checking files.
56
+ # exclude:
57
+ # - node_modules
58
+ # - vendor
21
59
  EOC
22
60
 
23
61
  attr_reader :stdout
@@ -93,6 +93,7 @@ module Goodcheck
93
93
  def rule_matches_example?(rule, example)
94
94
  buffer = Buffer.new(path: Pathname("-"), content: example)
95
95
  analyzer = Analyzer.new(rule: rule, buffer: buffer)
96
+ analyzer.use_all_patterns!
96
97
  analyzer.scan.count > 0
97
98
  end
98
99
  end
@@ -8,17 +8,33 @@ module Goodcheck
8
8
  @exclude_paths = exclude_paths
9
9
  end
10
10
 
11
+ def each_rule(filter:, &block)
12
+ if block_given?
13
+ if filter.empty?
14
+ rules.each(&block)
15
+ else
16
+ rules.each do |rule|
17
+ if filter.any? {|rule_id| rule.id == rule_id || rule.id.start_with?("#{rule_id}.") }
18
+ yield rule
19
+ end
20
+ end
21
+ end
22
+ else
23
+ enum_for :each_rule, filter: filter
24
+ end
25
+ end
26
+
11
27
  def rules_for_path(path, rules_filter:, &block)
12
28
  if block_given?
13
- rules.map do |rule|
14
- if rules_filter.empty? || rules_filter.any? {|filter| /\A#{Regexp.escape(filter)}\.?/ =~ rule.id }
15
- if rule.globs.empty?
16
- [rule, nil]
17
- else
18
- glob = rule.globs.find {|glob| path.fnmatch?(glob.pattern, File::FNM_PATHNAME | File::FNM_EXTGLOB) }
19
- if glob
20
- [rule, glob]
21
- end
29
+ each_rule(filter: rules_filter).map do |rule|
30
+ globs = rule.patterns.flat_map(&:globs).push(*rule.globs)
31
+
32
+ if globs.empty?
33
+ [rule, nil]
34
+ else
35
+ glob = globs.find {|glob| glob.test(path) }
36
+ if glob
37
+ [rule, glob]
22
38
  end
23
39
  end
24
40
  end.compact.each(&block)
@@ -5,48 +5,117 @@ module Goodcheck
5
5
  class InvalidPattern < StandardError; end
6
6
 
7
7
  Schema = StrongJSON.new do
8
+ def self.array_or(type)
9
+ a = array(type)
10
+ enum(a, type, detector: -> (value) {
11
+ case value
12
+ when Array
13
+ a
14
+ else
15
+ type
16
+ end
17
+ })
18
+ end
19
+
8
20
  let :deprecated_regexp_pattern, object(regexp: string, case_insensitive: boolean?, multiline: boolean?)
9
21
  let :deprecated_literal_pattern, object(literal: string, case_insensitive: boolean?)
10
22
  let :deprecated_token_pattern, object(token: string, case_insensitive: boolean?)
11
23
 
12
- let :regexp_pattern, object(regexp: string, case_sensitive: boolean?, multiline: boolean?)
13
- let :literal_pattern, object(literal: string, case_sensitive: boolean?)
14
- let :token_pattern, object(token: string, case_sensitive: boolean?)
15
-
16
- let :pattern, enum(regexp_pattern, literal_pattern, token_pattern,
17
- deprecated_regexp_pattern, deprecated_literal_pattern, deprecated_token_pattern,
18
- string)
19
-
20
24
  let :encoding, enum(*Encoding.name_list.map {|name| literal(name) })
21
- let :glob, object(pattern: string, encoding: optional(encoding))
25
+ let :glob_obj, object(pattern: string, encoding: optional(encoding))
26
+ let :one_glob, enum(glob_obj,
27
+ string,
28
+ detector: -> (value) {
29
+ case value
30
+ when Hash
31
+ glob_obj
32
+ when String
33
+ string
34
+ end
35
+ })
36
+ let :glob, array_or(one_glob)
37
+
38
+ let :regexp_pattern, object(regexp: string, case_sensitive: boolean?, multiline: boolean?, glob: optional(glob))
39
+ let :literal_pattern, object(literal: string, case_sensitive: boolean?, glob: optional(glob))
40
+ let :token_pattern, object(token: string, case_sensitive: boolean?, glob: optional(glob))
41
+
42
+ let :pattern, enum(regexp_pattern,
43
+ literal_pattern,
44
+ token_pattern,
45
+ deprecated_regexp_pattern,
46
+ deprecated_literal_pattern,
47
+ deprecated_token_pattern,
48
+ string,
49
+ detector: -> (value) {
50
+ case value
51
+ when Hash
52
+ case
53
+ when value.key?(:regexp) && value.key?(:case_insensitive)
54
+ deprecated_regexp_pattern
55
+ when value.key?(:regexp)
56
+ regexp_pattern
57
+ when value.key?(:literal) && value.key?(:case_insensitive)
58
+ deprecated_literal_pattern
59
+ when value.key?(:literal)
60
+ literal_pattern
61
+ when value.key?(:token) && value.key?(:case_insensitive)
62
+ deprecated_token_pattern
63
+ when value.key?(:token)
64
+ token_pattern
65
+ end
66
+ when String
67
+ string
68
+ end
69
+ })
22
70
 
23
71
  let :positive_rule, object(
24
72
  id: string,
25
- pattern: enum(array(pattern), pattern),
73
+ pattern: array_or(pattern),
26
74
  message: string,
27
- justification: optional(enum(array(string), string)),
28
- glob: optional(enum(array(enum(glob, string)), glob, string)),
29
- pass: optional(enum(array(string), string)),
30
- fail: optional(enum(array(string), string))
75
+ justification: optional(array_or(string)),
76
+ glob: optional(glob),
77
+ pass: optional(array_or(string)),
78
+ fail: optional(array_or(string))
31
79
  )
32
80
 
33
81
  let :negative_rule, object(
34
82
  id: string,
35
- not: object(pattern: enum(array(pattern), pattern)),
83
+ not: object(pattern: array_or(pattern)),
84
+ message: string,
85
+ justification: optional(array_or(string)),
86
+ glob: optional(glob),
87
+ pass: optional(array_or(string)),
88
+ fail: optional(array_or(string))
89
+ )
90
+
91
+ let :nopattern_rule, object(
92
+ id: string,
36
93
  message: string,
37
- justification: optional(enum(array(string), string)),
38
- glob: optional(enum(array(enum(glob, string)), glob, string)),
39
- pass: optional(enum(array(string), string)),
40
- fail: optional(enum(array(string), string))
94
+ justification: optional(array_or(string)),
95
+ glob: glob
41
96
  )
42
97
 
43
- let :rule, enum(positive_rule, negative_rule)
98
+ let :rule, enum(positive_rule,
99
+ negative_rule,
100
+ nopattern_rule,
101
+ detector: -> (hash) {
102
+ if hash.is_a?(Hash)
103
+ case
104
+ when hash[:pattern]
105
+ positive_rule
106
+ when hash[:not]
107
+ negative_rule
108
+ when hash.key?(:glob) && !hash.key?(:pattern) && !hash.key?(:not)
109
+ nopattern_rule
110
+ end
111
+ end
112
+ })
44
113
 
45
114
  let :rules, array(rule)
46
115
 
47
116
  let :import_target, string
48
117
  let :imports, array(import_target)
49
- let :exclude, enum(array(string), string)
118
+ let :exclude, array_or(string)
50
119
 
51
120
  let :config, object(
52
121
  rules: rules,
@@ -129,7 +198,11 @@ module Goodcheck
129
198
  negated = false
130
199
  end
131
200
 
132
- [array(hash[:pattern]).map {|pat| load_pattern(pat) }, negated]
201
+ if hash.key?(:pattern)
202
+ [array(hash[:pattern]).map {|pat| load_pattern(pat) }, negated]
203
+ else
204
+ [[], false]
205
+ end
133
206
  end
134
207
 
135
208
  def load_globs(globs)
@@ -148,20 +221,21 @@ module Goodcheck
148
221
  when String
149
222
  Pattern.literal(pattern, case_sensitive: true)
150
223
  when Hash
224
+ globs = load_globs(array(pattern[:glob]))
151
225
  case
152
226
  when pattern[:literal]
153
227
  cs = case_sensitive?(pattern)
154
228
  literal = pattern[:literal]
155
- Pattern.literal(literal, case_sensitive: cs)
229
+ Pattern.literal(literal, case_sensitive: cs, globs: globs)
156
230
  when pattern[:regexp]
157
231
  regexp = pattern[:regexp]
158
232
  cs = case_sensitive?(pattern)
159
233
  multiline = pattern[:multiline]
160
- Pattern.regexp(regexp, case_sensitive: cs, multiline: multiline)
234
+ Pattern.regexp(regexp, case_sensitive: cs, multiline: multiline, globs: globs)
161
235
  when pattern[:token]
162
236
  tok = pattern[:token]
163
237
  cs = case_sensitive?(pattern)
164
- Pattern.token(tok, case_sensitive: cs)
238
+ Pattern.token(tok, case_sensitive: cs, globs: globs)
165
239
  end
166
240
  end
167
241
  end
@@ -7,5 +7,9 @@ module Goodcheck
7
7
  @pattern = pattern
8
8
  @encoding = encoding
9
9
  end
10
+
11
+ def test(path)
12
+ path.fnmatch?(pattern, File::FNM_PATHNAME | File::FNM_EXTGLOB)
13
+ end
10
14
  end
11
15
  end
@@ -2,26 +2,40 @@ module Goodcheck
2
2
  class Pattern
3
3
  attr_reader :source
4
4
  attr_reader :regexp
5
+ attr_reader :globs
5
6
 
6
- def initialize(source:, regexp:)
7
+ def initialize(source:, regexp:, globs:)
7
8
  @source = source
8
9
  @regexp = regexp
10
+ @globs = globs
9
11
  end
10
12
 
11
- def self.literal(literal, case_sensitive:)
12
- new(source: literal, regexp: Regexp.compile(Regexp.escape(literal), !case_sensitive))
13
+ def self.literal(literal, case_sensitive:, globs: [])
14
+ new(
15
+ source: literal,
16
+ regexp: Regexp.compile(Regexp.escape(literal), !case_sensitive),
17
+ globs: globs
18
+ )
13
19
  end
14
20
 
15
- def self.regexp(regexp, case_sensitive:, multiline:)
21
+ def self.regexp(regexp, case_sensitive:, multiline:, globs: [])
16
22
  options = 0
17
23
  options |= Regexp::IGNORECASE unless case_sensitive
18
24
  options |= Regexp::MULTILINE if multiline
19
25
 
20
- new(source: regexp, regexp: Regexp.compile(regexp, options))
26
+ new(
27
+ source: regexp,
28
+ regexp: Regexp.compile(regexp, options),
29
+ globs: globs
30
+ )
21
31
  end
22
32
 
23
- def self.token(tokens, case_sensitive:)
24
- new(source: tokens, regexp: compile_tokens(tokens, case_sensitive: case_sensitive))
33
+ def self.token(tokens, case_sensitive:, globs: [])
34
+ new(
35
+ source: tokens,
36
+ regexp: compile_tokens(tokens, case_sensitive: case_sensitive),
37
+ globs: globs
38
+ )
25
39
  end
26
40
 
27
41
  def self.compile_tokens(source, case_sensitive:)
@@ -1,3 +1,3 @@
1
1
  module Goodcheck
2
- VERSION = "1.6.0"
2
+ VERSION = "1.7.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: goodcheck
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Soutaro Matsumoto
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-05-08 00:00:00.000000000 Z
11
+ date: 2019-05-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '5.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest-reporters
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 1.3.6
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 1.3.6
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: activesupport
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -78,14 +92,14 @@ dependencies:
78
92
  requirements:
79
93
  - - "~>"
80
94
  - !ruby/object:Gem::Version
81
- version: 0.7.1
95
+ version: 1.0.0
82
96
  type: :runtime
83
97
  prerelease: false
84
98
  version_requirements: !ruby/object:Gem::Requirement
85
99
  requirements:
86
100
  - - "~>"
87
101
  - !ruby/object:Gem::Version
88
- version: 0.7.1
102
+ version: 1.0.0
89
103
  - !ruby/object:Gem::Dependency
90
104
  name: rainbow
91
105
  requirement: !ruby/object:Gem::Requirement