simplecov 1.3.0 → 1.3.1
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/lib/simplecov/cli/affected/runner.rb +38 -0
- data/lib/simplecov/cli/affected.rb +4 -5
- data/lib/simplecov/cli/clean.rb +2 -1
- data/lib/simplecov/cli/coverage_file.rb +2 -1
- data/lib/simplecov/cli/real_path.rb +41 -0
- data/lib/simplecov/cli/serve/static_file_handler.rb +5 -3
- data/lib/simplecov/cli.rb +1 -0
- data/lib/simplecov/static_coverage_extractor/visitor.rb +1 -0
- data/lib/simplecov/static_coverage_extractor.rb +29 -9
- data/lib/simplecov/version.rb +1 -1
- data/lib/simplecov/view_coverage/template_compiler.rb +16 -7
- data/man/simplecov.1 +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c96bd7c97b97593cd5f90f20315a755ddbb9e25bd2b43ca54cc19fdf6c0540ac
|
|
4
|
+
data.tar.gz: 23b1b6392bfcf9119b2a5c575adf54568c47ef2c5838e11cbb77bffd72d61666
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3fb49f89386b147aa212d3b8814fb4afef021f394a2231c1e0649b5c35ea4e4ed14ba96cb9b8deacf1d6825629f56c55f900e3decaea287bff81f8a05d12b83f
|
|
7
|
+
data.tar.gz: a57ae0348b43869e6084866da885132c118acf88d83d967992d78aec222f8b6fab1ff6ab6572d3cc1ecdb2e701650aac9837ba45e963e64312ca8d3cdaaad1bd
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "English"
|
|
4
|
+
|
|
5
|
+
module SimpleCov
|
|
6
|
+
module CLI
|
|
7
|
+
module Affected
|
|
8
|
+
# Starts the runner at the repository root, since the selection's paths
|
|
9
|
+
# are relative to it, and answers the runner's exit status.
|
|
10
|
+
module SpawnedRunner
|
|
11
|
+
extend self
|
|
12
|
+
|
|
13
|
+
def call(command, root)
|
|
14
|
+
_, status = Process.wait2(spawn(*command, chdir: root))
|
|
15
|
+
status.exitstatus || 1
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# JRuby on Windows answers Process.wait2 with a nil status and ignores
|
|
20
|
+
# the chdir option Kernel#system takes, so there the runner starts
|
|
21
|
+
# inside Dir.chdir, and Kernel#system reports its status.
|
|
22
|
+
module SystemRunner
|
|
23
|
+
extend self
|
|
24
|
+
|
|
25
|
+
def call(command, root)
|
|
26
|
+
ran = Dir.chdir(root) { system(*command) }
|
|
27
|
+
raise Errno::ENOENT, command.first if ran.nil?
|
|
28
|
+
|
|
29
|
+
$CHILD_STATUS.exitstatus || 1
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# simplecov:disable branch — fixed by the running engine and OS
|
|
34
|
+
RUNNER = (RUBY_ENGINE.eql?("jruby") && Gem.win_platform?) ? SystemRunner : SpawnedRunner
|
|
35
|
+
# simplecov:enable branch
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -5,6 +5,7 @@ require "optparse"
|
|
|
5
5
|
require_relative "command_helpers"
|
|
6
6
|
require_relative "tests"
|
|
7
7
|
require_relative "affected/changed_files"
|
|
8
|
+
require_relative "affected/runner"
|
|
8
9
|
require_relative "affected/selection"
|
|
9
10
|
|
|
10
11
|
module SimpleCov
|
|
@@ -133,12 +134,10 @@ module SimpleCov
|
|
|
133
134
|
run_command(opts.fetch(:run) + selection.fetch(:tests), opts.fetch(:root), stderr)
|
|
134
135
|
end
|
|
135
136
|
|
|
136
|
-
# The
|
|
137
|
-
#
|
|
138
|
-
# every engine's exception message carries it.
|
|
137
|
+
# The command is named explicitly in the failure because not every
|
|
138
|
+
# engine's exception message carries it.
|
|
139
139
|
def run_command(command, root, stderr)
|
|
140
|
-
|
|
141
|
-
status.exitstatus || 1
|
|
140
|
+
RUNNER.call(command, root)
|
|
142
141
|
rescue SystemCallError => e
|
|
143
142
|
stderr.puts("simplecov affected: cannot run #{command.first.inspect} (#{e})")
|
|
144
143
|
127
|
data/lib/simplecov/cli/clean.rb
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require "fileutils"
|
|
4
4
|
require "optparse"
|
|
5
5
|
require_relative "command_helpers"
|
|
6
|
+
require_relative "real_path"
|
|
6
7
|
|
|
7
8
|
module SimpleCov
|
|
8
9
|
module CLI
|
|
@@ -68,7 +69,7 @@ module SimpleCov
|
|
|
68
69
|
end
|
|
69
70
|
|
|
70
71
|
def canonical_path(path)
|
|
71
|
-
|
|
72
|
+
REAL_PATHS.realpath(path)
|
|
72
73
|
rescue SystemCallError
|
|
73
74
|
File.expand_path(path)
|
|
74
75
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "../coverage_json"
|
|
4
|
+
require_relative "real_path"
|
|
4
5
|
|
|
5
6
|
module SimpleCov
|
|
6
7
|
module CLI
|
|
@@ -55,7 +56,7 @@ module SimpleCov
|
|
|
55
56
|
|
|
56
57
|
# A key whose file no longer exists keeps its literal spelling.
|
|
57
58
|
def normalize(key)
|
|
58
|
-
|
|
59
|
+
REAL_PATHS.realdirpath(key)
|
|
59
60
|
rescue SystemCallError
|
|
60
61
|
key
|
|
61
62
|
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleCov
|
|
4
|
+
module CLI
|
|
5
|
+
# The JDK's answer to File.realpath and File.realdirpath, for JRuby. On
|
|
6
|
+
# Windows JRuby's own versions follow no symlinks, and realdirpath accepts
|
|
7
|
+
# a directory that does not exist, so the CLI's containment and identity
|
|
8
|
+
# checks would compare paths that were never resolved. Path#toRealPath has
|
|
9
|
+
# neither problem on any OS. The path is expanded first because the JDK
|
|
10
|
+
# resolves a relative path against the JVM's working directory, which
|
|
11
|
+
# Dir.chdir does not move.
|
|
12
|
+
#
|
|
13
|
+
# simplecov:disable — JRuby-only; this suite's coverage is measured on CRuby
|
|
14
|
+
module JDKRealPath
|
|
15
|
+
extend self
|
|
16
|
+
|
|
17
|
+
# mutant:disable — JRuby-only, unreachable from the engine mutant runs on
|
|
18
|
+
def realpath(path)
|
|
19
|
+
expanded = File.expand_path(path)
|
|
20
|
+
java.nio.file.Paths.get(expanded).toRealPath.toString.tr("\\", "/") # steep:ignore NoMethod
|
|
21
|
+
rescue java.nio.file.NoSuchFileException, java.nio.file.NotDirectoryException # steep:ignore NoMethod
|
|
22
|
+
raise Errno::ENOENT, expanded
|
|
23
|
+
rescue java.nio.file.AccessDeniedException # steep:ignore NoMethod
|
|
24
|
+
raise Errno::EACCES, expanded
|
|
25
|
+
rescue java.nio.file.InvalidPathException # steep:ignore NoMethod
|
|
26
|
+
raise Errno::EINVAL, expanded
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# mutant:disable — JRuby-only, unreachable from the engine mutant runs on
|
|
30
|
+
def realdirpath(path)
|
|
31
|
+
expanded = File.expand_path(path)
|
|
32
|
+
return realpath(expanded) if File.exist?(expanded)
|
|
33
|
+
|
|
34
|
+
File.join(realpath(File.dirname(expanded)), File.basename(expanded))
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
# simplecov:enable
|
|
38
|
+
|
|
39
|
+
REAL_PATHS = RUBY_ENGINE.eql?("jruby") ? JDKRealPath : File # simplecov:disable branch — fixed by the running engine
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../real_path"
|
|
4
|
+
|
|
3
5
|
module SimpleCov
|
|
4
6
|
module CLI
|
|
5
7
|
module Serve
|
|
@@ -93,7 +95,7 @@ module SimpleCov
|
|
|
93
95
|
# added, it must happen BEFORE the `inside?` check.
|
|
94
96
|
def resolve(request_path, root)
|
|
95
97
|
path = request_path.split("?").first.to_s.delete_prefix("/")
|
|
96
|
-
absolute_root =
|
|
98
|
+
absolute_root = REAL_PATHS.realpath(root)
|
|
97
99
|
candidate = File.expand_path(path, absolute_root)
|
|
98
100
|
# Rejected before touching disk, so traversal and absolute-path attempts
|
|
99
101
|
# are 403, not 404.
|
|
@@ -104,10 +106,10 @@ module SimpleCov
|
|
|
104
106
|
|
|
105
107
|
# Symlinks are resolved last and re-checked: a file inside root could be
|
|
106
108
|
# a symlink pointing outside.
|
|
107
|
-
real =
|
|
109
|
+
real = REAL_PATHS.realpath(candidate)
|
|
108
110
|
inside?(real, absolute_root) ? real : :forbidden
|
|
109
111
|
rescue Errno::ENOENT
|
|
110
|
-
# TOCTOU: candidate vanished between File.file? and
|
|
112
|
+
# TOCTOU: candidate vanished between File.file? and resolving it.
|
|
111
113
|
nil
|
|
112
114
|
end
|
|
113
115
|
|
data/lib/simplecov/cli.rb
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "prism"
|
|
4
|
-
|
|
5
3
|
module SimpleCov
|
|
6
4
|
# Static enumeration of the branches and methods Ruby's `Coverage` library
|
|
7
5
|
# would have reported if a file had been loaded with `branches: true` /
|
|
@@ -14,14 +12,21 @@ module SimpleCov
|
|
|
14
12
|
# Position info comes from Prism's reported source locations; it doesn't
|
|
15
13
|
# always match `Coverage`'s byte-for-byte, but lines are reliable and
|
|
16
14
|
# downstream consumers that key off line numbers see the data they expect.
|
|
15
|
+
#
|
|
16
|
+
# Prism loads on the first extraction rather than with SimpleCov, so a
|
|
17
|
+
# line-only run never needs it. Where it cannot load at all (JRuby on
|
|
18
|
+
# Windows, whose FFI backend fails to open libprism), extraction answers nil
|
|
19
|
+
# like any other failure.
|
|
17
20
|
module StaticCoverageExtractor
|
|
18
21
|
extend self
|
|
19
22
|
|
|
20
23
|
# Parse `source` and return `{"branches" => {...}, "methods" => {...}}`
|
|
21
|
-
# matching the shape `Coverage.result[path]` produces. Returns nil
|
|
22
|
-
#
|
|
23
|
-
# hashes".
|
|
24
|
+
# matching the shape `Coverage.result[path]` produces. Returns nil when
|
|
25
|
+
# Prism cannot load or parsing fails, which callers treat as "couldn't
|
|
26
|
+
# extract, fall back to empty hashes".
|
|
24
27
|
def call(source)
|
|
28
|
+
return nil unless prism_loaded?
|
|
29
|
+
|
|
25
30
|
result = Prism.parse(source)
|
|
26
31
|
return nil if result.failure?
|
|
27
32
|
|
|
@@ -49,8 +54,8 @@ module SimpleCov
|
|
|
49
54
|
# Coincidental line-sharing between a real branch and an eval-generated one
|
|
50
55
|
# keeps both, an acceptable false-negative for an opt-in filter.
|
|
51
56
|
#
|
|
52
|
-
# Returns nil when parsing fails, signaling callers to
|
|
53
|
-
# entry.
|
|
57
|
+
# Returns nil when Prism cannot load or parsing fails, signaling callers to
|
|
58
|
+
# keep every Coverage entry.
|
|
54
59
|
def real_source_positions(source)
|
|
55
60
|
extracted = call(source)
|
|
56
61
|
return nil unless extracted
|
|
@@ -61,6 +66,14 @@ module SimpleCov
|
|
|
61
66
|
}
|
|
62
67
|
end
|
|
63
68
|
|
|
69
|
+
# Memoized, because a failed load leaves nothing in $LOADED_FEATURES and
|
|
70
|
+
# would otherwise be retried for every file.
|
|
71
|
+
def prism_loaded?
|
|
72
|
+
return @prism_loaded if instance_variable_defined?(:@prism_loaded)
|
|
73
|
+
|
|
74
|
+
@prism_loaded = load_prism
|
|
75
|
+
end
|
|
76
|
+
|
|
64
77
|
# Both keys carry their start line third, after the parts that vary between
|
|
65
78
|
# recordings. Read through a parameter list rather than an index, because
|
|
66
79
|
# every spelling of an index answers the same for a tuple of this fixed
|
|
@@ -72,7 +85,14 @@ module SimpleCov
|
|
|
72
85
|
def method_identity(_class_name, name, start_line, *)
|
|
73
86
|
[name, start_line]
|
|
74
87
|
end
|
|
88
|
+
|
|
89
|
+
private
|
|
90
|
+
|
|
91
|
+
def load_prism
|
|
92
|
+
require_relative "static_coverage_extractor/visitor"
|
|
93
|
+
true
|
|
94
|
+
rescue LoadError
|
|
95
|
+
false
|
|
96
|
+
end
|
|
75
97
|
end
|
|
76
98
|
end
|
|
77
|
-
|
|
78
|
-
require_relative "static_coverage_extractor/visitor"
|
data/lib/simplecov/version.rb
CHANGED
|
@@ -64,20 +64,29 @@ module SimpleCov
|
|
|
64
64
|
segments.fetch(-2).to_sym
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
-
#
|
|
68
|
-
#
|
|
69
|
-
#
|
|
70
|
-
#
|
|
71
|
-
# naming `.haml` behaves in a project that has no Haml: ActionView would
|
|
72
|
-
# hand back the raw handler and the template would report as static text.
|
|
67
|
+
# Nil when nothing is registered for the extension, which is how a default
|
|
68
|
+
# glob naming `.haml` behaves in a project that has no Haml.
|
|
69
|
+
# `handler_for_extension` is not that lookup: it falls back to the raw
|
|
70
|
+
# handler, and the template would report as static text.
|
|
73
71
|
def build_template(path, source)
|
|
74
72
|
extension = File.extname(path).delete_prefix(".")
|
|
75
|
-
handler =
|
|
73
|
+
handler = handler_for(extension)
|
|
76
74
|
return nil unless handler
|
|
77
75
|
|
|
78
76
|
no_locals = [] #: Array[Symbol]
|
|
79
77
|
ActionView::Template.new(source, path, handler, locals: no_locals, format: format_for(path))
|
|
80
78
|
end
|
|
79
|
+
|
|
80
|
+
# Rails main removed `Template.registered_template_handler` when the
|
|
81
|
+
# registry moved onto `Template::Handlers`. Read that hash directly so an
|
|
82
|
+
# unregistered extension stays nil. Older Rails still have the method.
|
|
83
|
+
def handler_for(extension)
|
|
84
|
+
if ActionView::Template.respond_to?(:registered_template_handler)
|
|
85
|
+
ActionView::Template.registered_template_handler(extension)
|
|
86
|
+
else
|
|
87
|
+
ActionView::Template::Handlers.template_handlers[extension.to_sym]
|
|
88
|
+
end
|
|
89
|
+
end
|
|
81
90
|
end
|
|
82
91
|
end
|
|
83
92
|
end
|
data/man/simplecov.1
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: simplecov
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.3.
|
|
4
|
+
version: 1.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Erik Berlin
|
|
@@ -43,6 +43,7 @@ files:
|
|
|
43
43
|
- lib/simplecov/cli.rb
|
|
44
44
|
- lib/simplecov/cli/affected.rb
|
|
45
45
|
- lib/simplecov/cli/affected/changed_files.rb
|
|
46
|
+
- lib/simplecov/cli/affected/runner.rb
|
|
46
47
|
- lib/simplecov/cli/affected/selection.rb
|
|
47
48
|
- lib/simplecov/cli/annotations.rb
|
|
48
49
|
- lib/simplecov/cli/badge.rb
|
|
@@ -68,6 +69,7 @@ files:
|
|
|
68
69
|
- lib/simplecov/cli/patch/output.rb
|
|
69
70
|
- lib/simplecov/cli/ratchet.rb
|
|
70
71
|
- lib/simplecov/cli/ratchet/output.rb
|
|
72
|
+
- lib/simplecov/cli/real_path.rb
|
|
71
73
|
- lib/simplecov/cli/report.rb
|
|
72
74
|
- lib/simplecov/cli/run.rb
|
|
73
75
|
- lib/simplecov/cli/serve.rb
|
|
@@ -239,9 +241,9 @@ licenses:
|
|
|
239
241
|
metadata:
|
|
240
242
|
bug_tracker_uri: https://github.com/simplecov-ruby/simplecov/issues
|
|
241
243
|
changelog_uri: https://github.com/simplecov-ruby/simplecov/blob/main/CHANGELOG.md
|
|
242
|
-
documentation_uri: https://www.rubydoc.info/gems/simplecov/1.3.
|
|
244
|
+
documentation_uri: https://www.rubydoc.info/gems/simplecov/1.3.1
|
|
243
245
|
mailing_list_uri: https://groups.google.com/forum/#!forum/simplecov
|
|
244
|
-
source_code_uri: https://github.com/simplecov-ruby/simplecov/tree/v1.3.
|
|
246
|
+
source_code_uri: https://github.com/simplecov-ruby/simplecov/tree/v1.3.1
|
|
245
247
|
rubygems_mfa_required: 'true'
|
|
246
248
|
rdoc_options: []
|
|
247
249
|
require_paths:
|
|
@@ -257,7 +259,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
257
259
|
- !ruby/object:Gem::Version
|
|
258
260
|
version: '0'
|
|
259
261
|
requirements: []
|
|
260
|
-
rubygems_version: 4.0.
|
|
262
|
+
rubygems_version: 4.0.21
|
|
261
263
|
specification_version: 4
|
|
262
264
|
summary: Code coverage for Ruby
|
|
263
265
|
test_files: []
|