codeclimate 0.14.2 → 0.14.3

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
  SHA1:
3
- metadata.gz: 72cddaaaf2d406b672e5dcf23810a2c3c12d5bf1
4
- data.tar.gz: 8d59b60cd8907a9ac2f797c355aaf74cc8c28e1e
3
+ metadata.gz: 10bc38c06b10a955c8f01ebb2275e7940b8c79c4
4
+ data.tar.gz: ed11b6c4343ab1a54a70b63d08b474700735d905
5
5
  SHA512:
6
- metadata.gz: dcae9739365b050502e5dbeded10610040236b0f9c8ca84b5a5559955f28c34101be489363874bd469748ec61218365f8cfd4fa0b89e6f67dfba122ae72b6609
7
- data.tar.gz: ffa9d0a75f6fdd2e615e5c1dc02b156c03f35e3f723d40845b9063f4016dbc4d09435fb0c43603cbeaf7cd9905378106bca83fb28409e0b630d8204a0c45ebb0
6
+ metadata.gz: 626e8011b55617172497200db09a1bf25401ad70805d17fe850d1ff1a67ab223cb294ea6a80fa46dc2502bc68ef91cb8d04fa547899a1b4c1ba408e64e507ebe
7
+ data.tar.gz: 0a99283ef527994d1ba32e29d84331549afd06c38cc3f580c6f0c8650c640b73b5a3c95e2c27689763b5a1e99e2b07a88d603271a9e24bb832fbba0dd8000fbe
data/config/engines.yml CHANGED
@@ -18,8 +18,12 @@ brakeman:
18
18
  enable_regexps:
19
19
  - ^script\/rails$
20
20
  default_ratings_paths:
21
- - "app/**"
21
+ - "Gemfile.lock"
22
+ - "**.erb"
23
+ - "**.haml"
22
24
  - "**.rb"
25
+ - "**.rhtml"
26
+ - "**.slim"
23
27
  bundler-audit:
24
28
  image: codeclimate/codeclimate-bundler-audit
25
29
  description: Patch-level verification for Bundler.
@@ -245,3 +245,9 @@ rules:
245
245
  yoda:
246
246
  - 0
247
247
  - never
248
+ env:
249
+ browser: true
250
+ node: true
251
+ jquery: true
252
+ amd: true
253
+ commonjs: true
data/lib/cc/analyzer.rb CHANGED
@@ -16,6 +16,7 @@ module CC
16
16
  autoload :LocationDescription, "cc/analyzer/location_description"
17
17
  autoload :LoggingContainerListener, "cc/analyzer/logging_container_listener"
18
18
  autoload :PathPatterns, "cc/analyzer/path_patterns"
19
+ autoload :PathMinimizer, "cc/analyzer/path_minimizer"
19
20
  autoload :RaisingContainerListener, "cc/analyzer/raising_container_listener"
20
21
  autoload :SourceBuffer, "cc/analyzer/source_buffer"
21
22
  autoload :StatsdContainerListener, "cc/analyzer/statsd_container_listener"
@@ -60,6 +60,7 @@ module CC
60
60
  duration = timeout
61
61
  @listener.timed_out(container_data(duration: duration))
62
62
  else
63
+ sleep 0.01 until !t_out.alive? && !t_err.alive?
63
64
  duration = ((Time.now - started) * 1000).round
64
65
  @listener.finished(container_data(duration: duration, status: status))
65
66
  end
@@ -30,9 +30,21 @@ module CC
30
30
  end
31
31
 
32
32
  def ignore_issue?(json)
33
+ check_disabled?(json) || ignore_fingerprint?(json)
34
+ end
35
+
36
+ def check_disabled?(json)
33
37
  !check_config(json["check_name"]).fetch("enabled", true)
34
38
  end
35
39
 
40
+ def ignore_fingerprint?(json)
41
+ if (fingerprint = json["fingerprint"])
42
+ @config.fetch("exclude_fingerprints", []).include?(fingerprint)
43
+ else
44
+ false
45
+ end
46
+ end
47
+
36
48
  def check_config(check_name)
37
49
  @checks ||= @config.fetch("checks", {})
38
50
  @checks.fetch(check_name, {})
@@ -29,6 +29,8 @@ module CC
29
29
 
30
30
  private
31
31
 
32
+ attr_reader :include_paths
33
+
32
34
  def engine_config(raw_engine_config)
33
35
  config = raw_engine_config.merge(
34
36
  exclude_paths: exclude_paths,
@@ -55,9 +57,7 @@ module CC
55
57
  end
56
58
 
57
59
  def include_paths
58
- IncludePathsBuilder.new(
59
- @config.exclude_paths || [], @requested_paths
60
- ).build
60
+ IncludePathsBuilder.new(exclude_paths, Array(@requested_paths)).build
61
61
  end
62
62
 
63
63
  def exclude_paths
@@ -47,7 +47,7 @@ module CC
47
47
  config: @config,
48
48
  container_label: @container_label,
49
49
  source_dir: @source_dir,
50
- requested_paths: @requested_paths,
50
+ requested_paths: requested_paths,
51
51
  ).run
52
52
  end
53
53
 
@@ -1,13 +1,11 @@
1
1
  require "file_utils_ext"
2
+ require "cc/analyzer/path_minimizer"
3
+ require "cc/analyzer/path_filter"
2
4
 
3
5
  module CC
4
6
  module Analyzer
5
7
  class IncludePathsBuilder
6
- def self.relevant_entries(path)
7
- Dir.entries(path).reject do |e|
8
- %w(. .. .git).include?(e) || File.symlink?(File.join(path, e))
9
- end
10
- end
8
+ IGNORE_PATHS = [".", "..", ".git"].freeze
11
9
 
12
10
  attr_reader :cc_include_paths
13
11
 
@@ -17,152 +15,47 @@ module CC
17
15
  end
18
16
 
19
17
  def build
20
- if cc_include_paths.any?
21
- paths = filter_by_cc_includes
22
- else
23
- root = Directory.new(".", ignored_files)
24
- paths = root.included_paths
25
- end
26
-
27
- paths.each do |path|
28
- raise_on_unreadable_files(path)
29
- end
18
+ PathMinimizer.new(paths_filter.paths).minimize.uniq
30
19
  end
31
20
 
32
- protected
21
+ private
22
+
23
+ def paths_filter
24
+ @_paths =
25
+ PathFilter.new(include_paths).
26
+ reject_paths(ignored_files).
27
+ raise_if_any_unreadable_files.
28
+ reject_unreadable_paths.
29
+ select_readable_files.
30
+ reject_symlinks
31
+ end
33
32
 
34
- def filter_by_cc_includes
35
- paths = []
36
- cc_include_paths.each do |path|
37
- if File.directory?(path)
38
- root = Directory.new(path, ignored_files)
39
- paths += root.included_paths
40
- elsif !ignored_files.include?(path)
41
- paths << path
33
+ def include_paths
34
+ if @cc_include_paths.empty?
35
+ all_paths
36
+ else
37
+ @cc_include_paths.flat_map do |path|
38
+ PathEntries.new(path).entries
42
39
  end
43
40
  end
44
- paths.uniq
41
+ end
42
+
43
+ def all_paths
44
+ Dir.glob("*", File::FNM_DOTMATCH).
45
+ reject { |path| IncludePathsBuilder::IGNORE_PATHS.include?(path) }.
46
+ flat_map { |path| PathEntries.new(path).entries }
45
47
  end
46
48
 
47
49
  def ignored_files
50
+ return @_ignored_files if @_ignored_files
51
+
48
52
  Tempfile.open(".cc_gitignore") do |tmp|
49
53
  tmp.write(File.read(".gitignore")) if File.file?(".gitignore")
50
54
  tmp << @cc_exclude_paths.join("\n")
51
55
  tmp.close
52
56
  tracked_and_ignored = `git ls-files -zi -X #{tmp.path} 2>/dev/null`.split("\0")
53
57
  untracked_and_ignored = `git ls-files -zio -X #{tmp.path} 2>/dev/null`.split("\0")
54
- tracked_and_ignored + untracked_and_ignored
55
- end
56
- end
57
-
58
- def raise_on_unreadable_files(path)
59
- if File.directory?(path)
60
- raise_on_unreadable_files_in_directory(path)
61
- elsif !FileUtils.readable_by_all?(path)
62
- raise CC::Analyzer::UnreadableFileError, "Can't read #{path}"
63
- end
64
- end
65
-
66
- def raise_on_unreadable_files_in_directory(path)
67
- IncludePathsBuilder.relevant_entries(path).each do |entry|
68
- sub_path = File.join(path, entry)
69
- raise_on_unreadable_files(sub_path)
70
- end
71
- end
72
-
73
- class Directory
74
- def initialize(path, excluded_files)
75
- @path = path
76
- @excluded_files = ensure_hashified(excluded_files)
77
- end
78
-
79
- def all_included?
80
- readable_by_all? &&
81
- files_all_included? &&
82
- subdirectories_all_included?
83
- end
84
-
85
- def included_paths
86
- if all_included?
87
- [@path + "/"]
88
- elsif readable_by_all?
89
- result = []
90
- result += included_file_entries
91
- result += included_subdirectory_results
92
- result
93
- else
94
- []
95
- end
96
- end
97
-
98
- protected
99
-
100
- def ensure_hashified(obj)
101
- if obj.is_a?(Array)
102
- obj.each_with_object({}) do |included, result|
103
- result[included] = true
104
- end
105
- else
106
- obj
107
- end
108
- end
109
-
110
- def files_all_included?
111
- file_entries.none? { |e| @excluded_files[e] }
112
- end
113
-
114
- def file_entries
115
- @file_entries ||= relevant_full_entries.reject do |e|
116
- File.directory?(e)
117
- end
118
- end
119
-
120
- def full_entry(entry)
121
- if @path == "."
122
- entry
123
- else
124
- File.join(@path, entry)
125
- end
126
- end
127
-
128
- def included_file_entries
129
- file_entries.reject { |file_entry| @excluded_files[file_entry] }
130
- end
131
-
132
- def included_subdirectory_results
133
- subdirectories.each_with_object([]) do |subdirectory, result|
134
- result.concat(subdirectory.included_paths)
135
- end
136
- end
137
-
138
- def readable_by_all?
139
- FileUtils.readable_by_all?(@path)
140
- end
141
-
142
- def relevant_full_entries
143
- unless @relevant_full_entries
144
- raw_entries = IncludePathsBuilder.relevant_entries(@path)
145
- @relevant_full_entries = raw_entries.map do |e|
146
- full_entry(e)
147
- end
148
- end
149
- @relevant_full_entries
150
- end
151
-
152
- def subdirectories
153
- unless @subdirectories
154
- entries = relevant_full_entries.select do |e|
155
- File.directory?(e)
156
- end
157
- @subdirectories = entries.map do |e|
158
- Directory.new(e, @excluded_files)
159
- end
160
- end
161
- @subdirectories
162
- end
163
-
164
- def subdirectories_all_included?
165
- subdirectories.all?(&:all_included?)
58
+ @_ignored_files = tracked_and_ignored + untracked_and_ignored
166
59
  end
167
60
  end
168
61
  end
@@ -16,13 +16,13 @@ module CC
16
16
 
17
17
  case
18
18
  when location["lines"]
19
- location["lines"]["begin"].to_i
19
+ [location["lines"]["begin"].to_i]
20
20
  when location["positions"] && location["positions"]["begin"]["line"]
21
- location["positions"]["begin"]["line"].to_i + location["positions"]["begin"]["column"].to_i
21
+ [location["positions"]["begin"]["line"].to_i, location["positions"]["begin"]["column"].to_i]
22
22
  when location["positions"] && location["positions"]["begin"]["offset"]
23
- location["positions"]["begin"]["offset"].to_i + 1_000_000_000 # push offsets to end of list
23
+ [1_000_000_000] # push offsets to end of list
24
24
  else
25
- 0 # whole-file issues are first
25
+ [0] # whole-file issues are first
26
26
  end
27
27
  end
28
28
  end
@@ -0,0 +1,27 @@
1
+ module CC
2
+ module Analyzer
3
+ class PathEntries
4
+ def initialize(initial_path)
5
+ @initial_path = initial_path.gsub(%r{/$}, "")
6
+ end
7
+
8
+ def entries
9
+ if File.directory?(initial_path)
10
+ all_entries.reject do |path|
11
+ path.end_with?("/.") || path.start_with?(".git/")
12
+ end
13
+ else
14
+ initial_path
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :initial_path
21
+
22
+ def all_entries
23
+ Dir.glob("#{initial_path}/**/*", File::FNM_DOTMATCH).push(initial_path)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,60 @@
1
+ module CC
2
+ module Analyzer
3
+ class PathFilter
4
+ attr_reader :paths
5
+
6
+ def initialize(paths)
7
+ @paths = paths
8
+ end
9
+
10
+ def raise_if_any_unreadable_files
11
+ paths.each do |path|
12
+ if !File.directory?(path) && !FileUtils.readable_by_all?(path)
13
+ raise CC::Analyzer::UnreadableFileError, "Can't read #{path}"
14
+ end
15
+ end
16
+
17
+ self
18
+ end
19
+
20
+ def reject_unreadable_paths
21
+ @paths = paths - unreadable_path_entries
22
+ self
23
+ end
24
+
25
+ def reject_paths(ignore_paths)
26
+ @paths = paths - ignore_paths
27
+ self
28
+ end
29
+
30
+ def select_readable_files
31
+ @paths = paths.select { |path| FileUtils.readable_by_all?(path) }
32
+ self
33
+ end
34
+
35
+ def reject_symlinks
36
+ @paths = paths.reject { |path| File.symlink?(path) }
37
+ self
38
+ end
39
+
40
+ def reject_globs(globs)
41
+ patterns = PathPatterns.new(globs)
42
+ @paths = paths.reject { |path| patterns.match?(pathpatterns.match?(path)) }
43
+ self
44
+ end
45
+
46
+ private
47
+
48
+ def unreadable_path_entries
49
+ @_unreadable_path_entries ||=
50
+ unreadable_paths.flat_map { |path| PathEntries.new(path).entries }
51
+ end
52
+
53
+ def unreadable_paths
54
+ paths.select do |path|
55
+ File.directory?(path) && !FileUtils.readable_by_all?(path)
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,84 @@
1
+ require "cc/analyzer/path_entries"
2
+ require "cc/analyzer/include_paths_builder"
3
+
4
+ module CC
5
+ module Analyzer
6
+ class PathMinimizer
7
+ def initialize(paths)
8
+ @paths = paths
9
+ @to_remove = []
10
+ end
11
+
12
+ def minimize
13
+ if diff.empty?
14
+ ["./"]
15
+ else
16
+ filtered_paths
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :paths
23
+
24
+ def diff
25
+ @_diff ||=
26
+ (all_files - paths).
27
+ reject { |path| File.symlink?(path) }.
28
+ flat_map { |path| build_entry_combinations(path) }
29
+ end
30
+
31
+ def filtered_paths
32
+ filtered_paths = @paths - paths_to_remove
33
+ filtered_paths.map { |path| add_trailing_slash(path) }
34
+ end
35
+
36
+ def paths_to_remove
37
+ @paths.reduce([]) do |to_remove, path|
38
+ if File.directory?(path)
39
+ to_remove + removable_paths_for(path)
40
+ else
41
+ to_remove
42
+ end
43
+ end
44
+ end
45
+
46
+ def removable_paths_for(path)
47
+ file_paths = PathEntries.new(path).entries
48
+
49
+ if all_paths_match?(file_paths)
50
+ file_paths - [path]
51
+ else
52
+ [path]
53
+ end
54
+ end
55
+
56
+ def all_paths_match?(paths)
57
+ paths.all? { |path| @paths.include?(path) }
58
+ end
59
+
60
+ def add_trailing_slash(path)
61
+ if File.directory?(path) && !path.end_with?("/")
62
+ "#{path}/"
63
+ else
64
+ path
65
+ end
66
+ end
67
+
68
+ def build_entry_combinations(path)
69
+ split = path.split("/")
70
+
71
+ 0.upto(split.length - 1).map do |n|
72
+ split[0..n].join("/")
73
+ end
74
+ end
75
+
76
+ def all_files
77
+ @_all_files ||=
78
+ Dir.glob("*", File::FNM_DOTMATCH).
79
+ reject { |path| IncludePathsBuilder::IGNORE_PATHS.include?(path) }.
80
+ flat_map { |path| PathEntries.new(path).entries }
81
+ end
82
+ end
83
+ end
84
+ end
@@ -6,6 +6,10 @@ module CC
6
6
  @root = root
7
7
  end
8
8
 
9
+ def match?(path)
10
+ expanded.include?(path)
11
+ end
12
+
9
13
  def expanded
10
14
  @expanded ||= expand
11
15
  end
@@ -15,25 +19,28 @@ module CC
15
19
  def expand
16
20
  results = Dir.chdir(@root) do
17
21
  @patterns.flat_map do |pattern|
18
- # FIXME: there exists a temporary workaround whereby **-style globs
19
- # are translated to **/*-style globs within cc-yaml's custom
20
- # Glob#value method. It was thought that that would work correctly
21
- # with Dir.glob but it turns out we have to actually invoke #value
22
- # directory for this to work. We need to guard this on class (not
23
- # respond_to?) because our mocking framework adds a #value method to
24
- # all objects, apparently.
25
- if pattern.is_a?(CC::Yaml::Nodes::Glob)
26
- value = pattern.value
27
- else
28
- value = pattern
29
- end
30
-
22
+ value = glob_value(pattern)
31
23
  Dir.glob(value)
32
24
  end
33
25
  end
34
26
 
35
27
  results.sort.uniq
36
28
  end
29
+
30
+ def glob_value(pattern)
31
+ # FIXME: there exists a temporary workaround whereby **-style globs
32
+ # are translated to **/*-style globs within cc-yaml's custom
33
+ # Glob#value method. It was thought that that would work correctly
34
+ # with Dir.glob but it turns out we have to actually invoke #value
35
+ # directrly for this to work. We need to guard this on class (not
36
+ # respond_to?) because our mocking framework adds a #value method to
37
+ # all objects, apparently.
38
+ if pattern.is_a?(CC::Yaml::Nodes::Glob)
39
+ pattern.value
40
+ else
41
+ pattern
42
+ end
43
+ end
37
44
  end
38
45
  end
39
46
  end
@@ -24,6 +24,10 @@ module CC
24
24
  run
25
25
  end
26
26
 
27
+ def success(message)
28
+ terminal.say colorize(message, :green)
29
+ end
30
+
27
31
  def say(message)
28
32
  terminal.say message
29
33
  end
data/lib/cc/cli/help.rb CHANGED
@@ -14,7 +14,7 @@ module CC
14
14
 
15
15
  def commands
16
16
  [
17
- "analyze [-f format]",
17
+ "analyze [-f format] [-e engine] <path>",
18
18
  "console",
19
19
  "engines:disable #{underline('engine_name')}",
20
20
  "engines:enable #{underline('engine_name')}",
data/lib/cc/cli/init.rb CHANGED
@@ -9,7 +9,8 @@ module CC
9
9
 
10
10
  def run
11
11
  if !upgrade? && filesystem.exist?(CODECLIMATE_YAML)
12
- fatal "Config file .codeclimate.yml already present.\nTry running 'validate-config' to check configuration."
12
+ warn "Config file .codeclimate.yml already present.\nTry running 'validate-config' to check configuration."
13
+ create_default_configs
13
14
  elsif upgrade? && engines_enabled?
14
15
  fatal "--upgrade should not be used on a .codeclimate.yml configured for the Platform.\nTry running 'validate-config' to check configuration."
15
16
  else
@@ -32,7 +33,7 @@ module CC
32
33
  end
33
34
 
34
35
  create_codeclimate_yaml
35
- say "Config file .codeclimate.yml successfully #{config_generator.post_generation_verb}.\nEdit and then try running 'validate-config' to check configuration."
36
+ success "Config file .codeclimate.yml successfully #{config_generator.post_generation_verb}.\nEdit and then try running 'validate-config' to check configuration."
36
37
  create_default_configs
37
38
  end
38
39
 
@@ -54,7 +55,7 @@ module CC
54
55
  say "Skipping generating #{file_name} file (already exists)."
55
56
  else
56
57
  filesystem.write_path(file_name, File.read(config_path))
57
- say "Config file #{file_name} successfully generated."
58
+ success "Config file #{file_name} successfully generated."
58
59
  end
59
60
  end
60
61
  end
data/lib/cc/cli/test.rb CHANGED
@@ -163,7 +163,7 @@ module CC
163
163
  def validate_unexpected_issues(actual_issues)
164
164
  if actual_issues.any?
165
165
  say colorize("Actuals not empty after matching.", :red)
166
- say
166
+ say "\n"
167
167
  say colorize("#{actual_issues.size} remaining:", :yellow)
168
168
  say colorize(JSON.pretty_generate(actual_issues), :yellow)
169
169
  fatal "Unexpected issue found."
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: codeclimate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.2
4
+ version: 0.14.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code Climate
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-10 00:00:00.000000000 Z
11
+ date: 2015-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -50,14 +50,14 @@ dependencies:
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: 0.5.0
53
+ version: 0.6.1
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: 0.5.0
60
+ version: 0.6.1
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: faraday
63
63
  requirement: !ruby/object:Gem::Requirement
@@ -218,6 +218,9 @@ files:
218
218
  - lib/cc/analyzer/issue_sorter.rb
219
219
  - lib/cc/analyzer/location_description.rb
220
220
  - lib/cc/analyzer/logging_container_listener.rb
221
+ - lib/cc/analyzer/path_entries.rb
222
+ - lib/cc/analyzer/path_filter.rb
223
+ - lib/cc/analyzer/path_minimizer.rb
221
224
  - lib/cc/analyzer/path_patterns.rb
222
225
  - lib/cc/analyzer/raising_container_listener.rb
223
226
  - lib/cc/analyzer/source_buffer.rb