uncov 0.4.2 → 0.6.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 +26 -0
- data/README.md +36 -5
- data/lib/{uncov → plugins/uncov}/formatter/terminal.rb +24 -7
- data/lib/plugins/uncov/report/filters/diff_files.rb +33 -0
- data/lib/plugins/uncov/report/filters/diff_lines.rb +33 -0
- data/lib/plugins/uncov/report/filters/file_system.rb +33 -0
- data/lib/plugins/uncov/report/filters/git_files.rb +33 -0
- data/lib/plugins/uncov/report/filters/nocov_lines.rb +35 -0
- data/lib/plugins/uncov/report/filters/simplecov.rb +33 -0
- data/lib/uncov/cli.rb +2 -2
- data/lib/uncov/configuration/option.rb +10 -4
- data/lib/uncov/configuration.rb +44 -12
- data/lib/uncov/finder/file_system.rb +14 -4
- data/lib/uncov/finder/files.rb +30 -0
- data/lib/uncov/finder/git.rb +26 -6
- data/lib/uncov/finder/git_base.rb +10 -2
- data/lib/uncov/finder/git_diff.rb +41 -26
- data/lib/uncov/finder/{no_cov.rb → nocov.rb} +6 -8
- data/lib/uncov/finder/{simple_cov.rb → simplecov.rb} +20 -5
- data/lib/uncov/finder.rb +66 -30
- data/lib/uncov/formatter.rb +5 -18
- data/lib/uncov/report/context.rb +24 -0
- data/lib/uncov/report/file/line.rb +24 -5
- data/lib/uncov/report/file.rb +14 -14
- data/lib/uncov/report/filters.rb +20 -0
- data/lib/uncov/report.rb +18 -19
- data/lib/uncov/version.rb +1 -1
- data/lib/uncov.rb +27 -7
- metadata +29 -8
- data/lib/uncov/report/diff_lines.rb +0 -63
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fc5eb3c1149eba5de56dd2bd43a4bf9a450abc25689456ef9290da0bb903b657
|
4
|
+
data.tar.gz: '08567ab62f909c0b8ebdf9f8bc8793edcb0e96e77408b10a5249da61cab7e42d'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 849aec6d7483b7e76349d714ed59a7c53f0f3d9dd7c04e1423b808c0f00559274ef541fff97a024e001f7861a171c1079769229bc2bb2652500568f14f1f4283
|
7
|
+
data.tar.gz: 07eda0122c302e6003ed972585f7d0103985bbf56a5bf778029a3c3591ab9535cc94c8d3b83cc211f94eace1ebf495ef10eb365d8339807179e3ec3d8e294ad7
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,31 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 2025-05-26: [v0.6.0](https://github.com/mpapis/uncov/releases/tag/v0.6.0)
|
4
|
+
|
5
|
+
### Minor
|
6
|
+
|
7
|
+
- [#47](https://github.com/mpapis/uncov/pull/47): Extensible with plugins, by [@mpapis](https://github.com/mpapis)
|
8
|
+
- [#56](https://github.com/mpapis/uncov/pull/56): Add Simplecov and FileSystem filters, by [@mpapis](https://github.com/mpapis)
|
9
|
+
|
10
|
+
### Patch
|
11
|
+
|
12
|
+
- [#59](https://github.com/mpapis/uncov/pull/59): Simplify git rev-parse target, by [@mpapis](https://github.com/mpapis)
|
13
|
+
|
14
|
+
|
15
|
+
## 2025-05-12: [v0.5.0](https://github.com/mpapis/uncov/releases/tag/v0.5.0)
|
16
|
+
|
17
|
+
### Minor
|
18
|
+
|
19
|
+
- [#43](https://github.com/mpapis/uncov/pull/43): Trigger tests on test_file_changes. Add git_files report generator., by [@mpapis](https://github.com/mpapis)
|
20
|
+
- [#45](https://github.com/mpapis/uncov/pull/45): Add diff_files report type, by [@mpapis](https://github.com/mpapis)
|
21
|
+
- [#46](https://github.com/mpapis/uncov/pull/46): Add nocov report filter and flags, by [@mpapis](https://github.com/mpapis)
|
22
|
+
|
23
|
+
### Patch
|
24
|
+
|
25
|
+
- [#44](https://github.com/mpapis/uncov/pull/44): Allow any git revision specification for target, by [@mpapis](https://github.com/mpapis)
|
26
|
+
|
27
|
+
|
28
|
+
|
3
29
|
## 2025-05-10: [v0.4.2](https://github.com/mpapis/uncov/releases/tag/v0.4.2)
|
4
30
|
|
5
31
|
### Patch
|
data/README.md
CHANGED
@@ -13,6 +13,8 @@ Uncov uses `git diff` to detect changes and `simplecov` reports to detect uncove
|
|
13
13
|
- Identify changed Ruby files
|
14
14
|
- Run tests automatically for (changed) relevant files
|
15
15
|
- Print report of uncovered lines in (changed) files
|
16
|
+
- Print report of covered :nocov: lines in (changed) files
|
17
|
+
- Extensible with gem plugins
|
16
18
|
|
17
19
|
|
18
20
|
## Installation
|
@@ -36,16 +38,35 @@ uncov
|
|
36
38
|
$ uncov -h
|
37
39
|
Usage: uncov [options]
|
38
40
|
-t, --target TARGET Target branch for comparison, default: "HEAD"
|
39
|
-
-r, --report
|
40
|
-
-o, --output-format FORMAT Output format, one_of: "
|
41
|
+
-r, --report FILTER Report filter to generate file/line list, one_of: "DiffFiles", "DiffLines"(default), "FileSystem", "GitFiles", "NocovLines", "Simplecov"
|
42
|
+
-o, --output-format FORMAT Output format, one_of: "Terminal"(default)
|
41
43
|
-C, --context LINES_NUMBER Additional lines context in output, default: 1
|
42
44
|
--test-command COMMAND Test command that generates SimpleCov, default: "COVERAGE=true bundle exec rake test"
|
43
45
|
--simplecov-file PATH SimpleCov results file, default: "autodetect"
|
44
|
-
--relevant-files
|
46
|
+
--relevant-files FN_GLOB Only show uncov for matching code files AND trigger tests if matching code files are newer than the report, default: "{{bin,exe,exec}/*,{app,lib}/**/*.{rake,rb},Rakefile}"
|
47
|
+
--relevant-tests FN_GLOB Trigger tests if matching test files are newer than the report, default: "{test,spec}/**/*_{test,spec}.rb"
|
48
|
+
--nocov-ignore Ignore :nocov: markers - consider all lines, default: false
|
49
|
+
--nocov-covered Report :nocov: lines that have coverage, default: false
|
45
50
|
--debug Get some insights, default: false
|
46
|
-
-v, --version Show version
|
47
51
|
-h, --help Print this help
|
48
|
-
|
52
|
+
|
53
|
+
Report FILTERs:
|
54
|
+
DiffFiles - Report missing coverage on added/changed files in the git diff
|
55
|
+
DiffLines - Report missing coverage on added lines in the git diff
|
56
|
+
FileSystem - Report missing coverage on file system
|
57
|
+
GitFiles - Report missing coverage on files tracked with git
|
58
|
+
NocovLines - Report coverage on nocov lines, requires one or both: --nocov-ignore / --nocov-covered
|
59
|
+
Simplecov - Report missing coverage on files tracked with simplecov
|
60
|
+
|
61
|
+
Report FILTERs take NOTICE:
|
62
|
+
git*/diff* - filters will not consider new files unless added to the git index with `git add`.
|
63
|
+
nocov* - filters/flags only work with coverage/.resultset.json SimpleCov files,
|
64
|
+
coverage.json does not provide the information needed.
|
65
|
+
|
66
|
+
FN_GLOB: shell filename globing -> https://ruby-doc.org/core-3.1.1/File.html#method-c-fnmatch
|
67
|
+
in bash: `shopt -s extglob dotglob globstar` and test with `ls {app,lib}/**/*.rb`
|
68
|
+
|
69
|
+
uncov 0.6.0 by Michal Papis <mpapis@gmail.com>
|
49
70
|
```
|
50
71
|
|
51
72
|
|
@@ -62,6 +83,16 @@ COVERAGE=1 rspec
|
|
62
83
|
```
|
63
84
|
|
64
85
|
|
86
|
+
## Plugins
|
87
|
+
Uncov uses [pluginator](https://github.com/rvm/pluginator) to load plugins.
|
88
|
+
|
89
|
+
See [lib/plugins/uncov](lib/plugins/uncov) for default plugins.
|
90
|
+
|
91
|
+
To create your own plugin, create a gem with a `lib/plugins/uncov/...` structure - same as uncov has,
|
92
|
+
the plugins will be loaded automatically.
|
93
|
+
|
94
|
+
When you use uncov from a Gemfile then the new gam has to be added there too.
|
95
|
+
|
65
96
|
## Using in CI
|
66
97
|
`uncov` uses itself to check new missing code coverage [.github/workflows/ci.yml](.github/workflows/ci.yml),
|
67
98
|
no need to set minimal, always get better.
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'colorize'
|
4
|
-
require 'forwardable'
|
5
4
|
|
6
5
|
# print report to terminal with colors
|
7
6
|
class Uncov::Formatter::Terminal
|
@@ -14,14 +13,20 @@ class Uncov::Formatter::Terminal
|
|
14
13
|
end
|
15
14
|
|
16
15
|
def output
|
17
|
-
puts
|
16
|
+
return puts 'No files to report.'.green if report.files.empty?
|
17
|
+
return puts "All changed files(#{report.files.count}) have 100% test coverage!".green unless report.trigger?
|
18
|
+
|
19
|
+
output_header
|
18
20
|
output_files
|
19
|
-
|
20
|
-
|
21
|
+
output_summary
|
22
|
+
end
|
23
|
+
|
24
|
+
def output_header
|
25
|
+
puts "Files with uncovered changes: (#{report.display_files.size} / #{report.files.count})".yellow
|
21
26
|
end
|
22
27
|
|
23
28
|
def output_files
|
24
|
-
report.
|
29
|
+
report.display_files.each do |file_coverage|
|
25
30
|
output_file(file_coverage)
|
26
31
|
end
|
27
32
|
end
|
@@ -40,8 +45,8 @@ class Uncov::Formatter::Terminal
|
|
40
45
|
'%<name>s -> %<coverage>.2f%% (%<covered_lines>d / %<relevant_lines>d) changes covered, uncovered lines:',
|
41
46
|
name: file_coverage.file_name,
|
42
47
|
coverage: file_coverage.coverage,
|
43
|
-
covered_lines: file_coverage.
|
44
|
-
relevant_lines: file_coverage.
|
48
|
+
covered_lines: file_coverage.covered_lines_count,
|
49
|
+
relevant_lines: file_coverage.relevant_lines_count
|
45
50
|
).yellow
|
46
51
|
end
|
47
52
|
|
@@ -50,6 +55,8 @@ class Uncov::Formatter::Terminal
|
|
50
55
|
puts format_line(line, max).red
|
51
56
|
elsif line.context
|
52
57
|
puts format_line(line, max).green
|
58
|
+
elsif line.nocov_covered?
|
59
|
+
puts format_line(line, max).blue
|
53
60
|
else
|
54
61
|
# :nocov:
|
55
62
|
raise 'unknown display line' # unreachable code
|
@@ -64,4 +71,14 @@ class Uncov::Formatter::Terminal
|
|
64
71
|
def number_length(file_coverage)
|
65
72
|
file_coverage.display_lines.last.number.to_s.length
|
66
73
|
end
|
74
|
+
|
75
|
+
def output_summary
|
76
|
+
puts
|
77
|
+
puts format(
|
78
|
+
'Overall coverage of changes: %<coverage>.2f%% (%<covered_lines>d / %<relevant_lines>d)',
|
79
|
+
coverage: report.coverage,
|
80
|
+
covered_lines: report.covered_lines_count,
|
81
|
+
relevant_lines: report.relevant_lines_count
|
82
|
+
).yellow
|
83
|
+
end
|
67
84
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# report only files lines from the diff
|
4
|
+
module Uncov::Report::Filters::DiffFiles
|
5
|
+
class << self
|
6
|
+
def description = 'Report missing coverage on added/changed files in the git diff'
|
7
|
+
def simplecov_trigger = :git_diff
|
8
|
+
|
9
|
+
def files(finder)
|
10
|
+
finder.git_diff_files.file_names.map do |file_name|
|
11
|
+
Uncov::Report::File.new(
|
12
|
+
file_name:,
|
13
|
+
git: true,
|
14
|
+
lines: lines(finder, file_name)
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def lines(finder, file_name)
|
22
|
+
lines_hash = file_lines(finder, file_name)
|
23
|
+
Uncov::Report::Context.add_context(finder, file_name, lines_hash)
|
24
|
+
lines_hash.sort.to_h.values
|
25
|
+
end
|
26
|
+
|
27
|
+
def file_lines(finder, file_name)
|
28
|
+
finder.file_system_files.lines(file_name).keys.to_h do |line_number|
|
29
|
+
[line_number, finder.build_line(file_name, line_number)]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# report only files lines from the diff
|
4
|
+
module Uncov::Report::Filters::DiffLines
|
5
|
+
class << self
|
6
|
+
def description = 'Report missing coverage on added lines in the git diff'
|
7
|
+
def simplecov_trigger = :git_diff
|
8
|
+
|
9
|
+
def files(finder)
|
10
|
+
finder.git_diff_files.file_names.map do |file_name|
|
11
|
+
Uncov::Report::File.new(
|
12
|
+
file_name:,
|
13
|
+
git: true,
|
14
|
+
lines: lines(finder, file_name)
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def lines(finder, file_name)
|
22
|
+
lines_hash = git_diff_files_lines(finder, file_name)
|
23
|
+
Uncov::Report::Context.add_context(finder, file_name, lines_hash)
|
24
|
+
lines_hash.sort.to_h.values
|
25
|
+
end
|
26
|
+
|
27
|
+
def git_diff_files_lines(finder, file_name)
|
28
|
+
finder.git_diff_files.lines(file_name).keys.to_h do |line_number|
|
29
|
+
[line_number, finder.build_line(file_name, line_number)]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# report all files lines from the file system
|
4
|
+
module Uncov::Report::Filters::FileSystem
|
5
|
+
class << self
|
6
|
+
def description = 'Report missing coverage on file system'
|
7
|
+
def simplecov_trigger = :file_system
|
8
|
+
|
9
|
+
def files(finder)
|
10
|
+
finder.file_system_files.file_names.map do |file_name|
|
11
|
+
Uncov::Report::File.new(
|
12
|
+
file_name:,
|
13
|
+
git: finder.git_files.file?(file_name),
|
14
|
+
lines: lines(finder, file_name)
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def lines(finder, file_name)
|
22
|
+
lines_hash = file_lines(finder, file_name)
|
23
|
+
Uncov::Report::Context.add_context(finder, file_name, lines_hash)
|
24
|
+
lines_hash.sort.to_h.values
|
25
|
+
end
|
26
|
+
|
27
|
+
def file_lines(finder, file_name)
|
28
|
+
finder.file_system_files.lines(file_name).keys.to_h do |line_number|
|
29
|
+
[line_number, finder.build_line(file_name, line_number)]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# report only files lines from the diff
|
4
|
+
module Uncov::Report::Filters::GitFiles
|
5
|
+
class << self
|
6
|
+
def description = 'Report missing coverage on files tracked with git'
|
7
|
+
def simplecov_trigger = :git
|
8
|
+
|
9
|
+
def files(finder)
|
10
|
+
finder.git_files.file_names.map do |file_name|
|
11
|
+
Uncov::Report::File.new(
|
12
|
+
file_name:,
|
13
|
+
git: true,
|
14
|
+
lines: lines(finder, file_name)
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def lines(finder, file_name)
|
22
|
+
lines_hash = file_lines(finder, file_name)
|
23
|
+
Uncov::Report::Context.add_context(finder, file_name, lines_hash)
|
24
|
+
lines_hash.sort.to_h.values
|
25
|
+
end
|
26
|
+
|
27
|
+
def file_lines(finder, file_name)
|
28
|
+
finder.file_system_files.lines(file_name).keys.to_h do |line_number|
|
29
|
+
[line_number, finder.build_line(file_name, line_number)]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# report only files lines from the diff
|
4
|
+
module Uncov::Report::Filters::NocovLines
|
5
|
+
class << self
|
6
|
+
def description = 'Report coverage on nocov lines, requires one or both: --nocov-ignore / --nocov-covered'
|
7
|
+
def simplecov_trigger = :file_system
|
8
|
+
|
9
|
+
def files(finder)
|
10
|
+
finder.nocov_files.file_names.filter_map do |file_name|
|
11
|
+
next if finder.nocov_files.lines(file_name).empty?
|
12
|
+
|
13
|
+
Uncov::Report::File.new(
|
14
|
+
file_name:,
|
15
|
+
git: finder.git_files.file?(file_name),
|
16
|
+
lines: lines(finder, file_name)
|
17
|
+
)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def lines(finder, file_name)
|
24
|
+
lines_hash = nocov_files_lines(finder, file_name)
|
25
|
+
Uncov::Report::Context.add_context(finder, file_name, lines_hash)
|
26
|
+
lines_hash.sort.to_h.values
|
27
|
+
end
|
28
|
+
|
29
|
+
def nocov_files_lines(finder, file_name)
|
30
|
+
finder.nocov_files.lines(file_name).keys.to_h do |line_number|
|
31
|
+
[line_number, finder.build_line(file_name, line_number)]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# report only files lines from the simplecov
|
4
|
+
module Uncov::Report::Filters::Simplecov
|
5
|
+
class << self
|
6
|
+
def description = 'Report missing coverage on files tracked with simplecov'
|
7
|
+
def simplecov_trigger = :file_system
|
8
|
+
|
9
|
+
def files(finder)
|
10
|
+
finder.simplecov_files.file_names.map do |file_name|
|
11
|
+
Uncov::Report::File.new(
|
12
|
+
file_name:,
|
13
|
+
git: finder.git_files.file?(file_name),
|
14
|
+
lines: lines(finder, file_name)
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def lines(finder, file_name)
|
22
|
+
lines_hash = file_lines(finder, file_name)
|
23
|
+
Uncov::Report::Context.add_context(finder, file_name, lines_hash)
|
24
|
+
lines_hash.sort.to_h.values
|
25
|
+
end
|
26
|
+
|
27
|
+
def file_lines(finder, file_name)
|
28
|
+
finder.file_system_files.lines(file_name).keys.to_h do |line_number|
|
29
|
+
[line_number, finder.build_line(file_name, line_number)]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/uncov/cli.rb
CHANGED
@@ -6,9 +6,9 @@ require 'optparse'
|
|
6
6
|
class Uncov::CLI
|
7
7
|
def self.start(args)
|
8
8
|
Uncov.configure(args)
|
9
|
-
report = Uncov::Report.
|
9
|
+
report = Uncov::Report.generate
|
10
10
|
Uncov::Formatter.output(report)
|
11
|
-
!report.
|
11
|
+
!report.trigger?
|
12
12
|
rescue StandardError => e
|
13
13
|
raise if Uncov.configuration.debug
|
14
14
|
|
@@ -2,16 +2,16 @@
|
|
2
2
|
|
3
3
|
# configuration option
|
4
4
|
class Uncov::Configuration::Option
|
5
|
-
attr_reader :name, :description, :options, :default, :
|
5
|
+
attr_reader :name, :description, :options, :default, :value_parse, :value
|
6
6
|
|
7
7
|
def initialize(name, description, options, default, allowed_values, value_parse)
|
8
8
|
@name = name
|
9
9
|
@description = description
|
10
10
|
@options = Array(options)
|
11
11
|
@default = default.freeze
|
12
|
+
@value = default
|
12
13
|
@allowed_values = allowed_values
|
13
14
|
@value_parse = value_parse
|
14
|
-
self.value = default
|
15
15
|
end
|
16
16
|
|
17
17
|
def value=(value)
|
@@ -41,10 +41,16 @@ class Uncov::Configuration::Option
|
|
41
41
|
if value == default
|
42
42
|
"#{value.inspect}(default)"
|
43
43
|
else
|
44
|
-
# :nocov: for now as there is no case yet in Configuration
|
45
44
|
value.inspect
|
46
|
-
# :nocov:
|
47
45
|
end
|
48
46
|
end
|
49
47
|
end
|
48
|
+
|
49
|
+
def allowed_values
|
50
|
+
if @allowed_values.respond_to?(:call)
|
51
|
+
@allowed_values = @allowed_values.call
|
52
|
+
else
|
53
|
+
@allowed_values
|
54
|
+
end
|
55
|
+
end
|
50
56
|
end
|
data/lib/uncov/configuration.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'formatter'
|
4
|
-
require_relative 'report'
|
4
|
+
require_relative 'report/filters'
|
5
5
|
|
6
6
|
# handle configuration for uncov
|
7
7
|
class Uncov::Configuration
|
8
8
|
CONFIG_FILE = '.uncov'
|
9
|
+
# equivalent of `shopt -s extglob dotglob globstar` for testing with `bash` & `ls`
|
9
10
|
FILE_MATCH_FLAGS = File::FNM_EXTGLOB | File::FNM_PATHNAME | File::FNM_DOTMATCH
|
10
11
|
|
11
12
|
class << self
|
@@ -19,16 +20,23 @@ class Uncov::Configuration
|
|
19
20
|
end
|
20
21
|
|
21
22
|
option 'target', 'Target branch for comparison', options: ['-t', '--target TARGET'], default: 'HEAD'
|
22
|
-
option 'report', 'Report
|
23
|
+
option 'report', 'Report filter to generate file/line list',
|
24
|
+
options: ['-r', '--report FILTER'], default: 'DiffLines', allowed_values: -> { Uncov::Report::Filters.filters.keys }
|
23
25
|
option 'output_format', 'Output format',
|
24
|
-
options: ['-o', '--output-format FORMAT'], default: '
|
26
|
+
options: ['-o', '--output-format FORMAT'], default: 'Terminal', allowed_values: -> { Uncov::Formatter.formatters.keys }
|
25
27
|
option 'context', 'Additional lines context in output',
|
26
28
|
options: ['-C', '--context LINES_NUMBER'], default: 1, value_parse: lambda(&:to_i)
|
27
29
|
option 'test_command', 'Test command that generates SimpleCov',
|
28
30
|
options: '--test-command COMMAND', default: 'COVERAGE=true bundle exec rake test'
|
29
31
|
option 'simplecov_file', 'SimpleCov results file', options: '--simplecov-file PATH', default: 'autodetect'
|
30
|
-
option 'relevant_files', '
|
31
|
-
options: '--relevant-files', default: '{{bin,exe,exec}/*,{app,lib}/**/*.{rake,rb},Rakefile}'
|
32
|
+
option 'relevant_files', 'Only show uncov for matching code files AND trigger tests if matching code files are newer than the report',
|
33
|
+
options: '--relevant-files FN_GLOB', default: '{{bin,exe,exec}/*,{app,lib}/**/*.{rake,rb},Rakefile}'
|
34
|
+
option 'relevant_tests', 'Trigger tests if matching test files are newer than the report',
|
35
|
+
options: '--relevant-tests FN_GLOB', default: '{test,spec}/**/*_{test,spec}.rb'
|
36
|
+
option 'nocov_ignore', 'Ignore :nocov: markers - consider all lines',
|
37
|
+
options: '--nocov-ignore', default: false, value_parse: ->(_value) { true }
|
38
|
+
option 'nocov_covered', 'Report :nocov: lines that have coverage',
|
39
|
+
options: '--nocov-covered', default: false, value_parse: ->(_value) { true }
|
32
40
|
option 'debug', 'Get some insights', options: '--debug', default: false, value_parse: ->(_value) { true }
|
33
41
|
|
34
42
|
def initialize
|
@@ -66,16 +74,40 @@ class Uncov::Configuration
|
|
66
74
|
def parser_header(parser) = parser.banner = 'Usage: uncov [options]'
|
67
75
|
|
68
76
|
def parser_footer(parser)
|
69
|
-
parser.on('-v', '--version', 'Show version') do
|
70
|
-
puts "uncov #{Uncov::VERSION} by Michal Papis <mpapis@gmail.com>"
|
71
|
-
throw :exit, 0
|
72
|
-
end
|
73
77
|
parser.on('-h', '--help', 'Print this help') do
|
74
|
-
puts parser
|
75
|
-
puts "uncov #{Uncov::VERSION} by Michal Papis <mpapis@gmail.com>"
|
78
|
+
puts parser.help
|
76
79
|
throw :exit, 0
|
77
80
|
end
|
81
|
+
footer_extras(parser)
|
78
82
|
end
|
79
83
|
|
80
|
-
def
|
84
|
+
def footer_extras(parser)
|
85
|
+
# TODO: the release workflow does not like ' in help, please avoid it - or fix the workflow
|
86
|
+
parser.separator <<~HELP
|
87
|
+
|
88
|
+
Report FILTERs:
|
89
|
+
#{footer_extras_types}
|
90
|
+
|
91
|
+
Report FILTERs take NOTICE:
|
92
|
+
git*/diff* - filters will not consider new files unless added to the git index with `git add`.
|
93
|
+
nocov* - filters/flags only work with coverage/.resultset.json SimpleCov files,
|
94
|
+
coverage.json does not provide the information needed.
|
95
|
+
|
96
|
+
FN_GLOB: shell filename globing -> https://ruby-doc.org/core-3.1.1/File.html#method-c-fnmatch
|
97
|
+
in bash: `shopt -s extglob dotglob globstar` and test with `ls {app,lib}/**/*.rb`
|
98
|
+
|
99
|
+
uncov #{Uncov::VERSION} by Michal Papis <mpapis@gmail.com>
|
100
|
+
HELP
|
101
|
+
end
|
102
|
+
|
103
|
+
def footer_extras_types
|
104
|
+
report_type_length = Uncov::Report::Filters.filters.keys.map(&:length).max
|
105
|
+
Uncov::Report::Filters.filters.map do |name, filter|
|
106
|
+
format("%#{report_type_length}s - %s", name, filter.description)
|
107
|
+
end.join("\n")
|
108
|
+
end
|
109
|
+
|
110
|
+
def options
|
111
|
+
@options ||= {}
|
112
|
+
end
|
81
113
|
end
|
@@ -4,15 +4,25 @@
|
|
4
4
|
class Uncov::Finder::FileSystem
|
5
5
|
include Uncov::Cache
|
6
6
|
|
7
|
-
def
|
7
|
+
def code_files
|
8
|
+
list_files(Uncov.configuration.relevant_files).to_h do |file_name|
|
9
|
+
[file_name, read_lines(file_name)]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def simplecov_trigger_files
|
14
|
+
code_files.keys + test_files
|
15
|
+
end
|
8
16
|
|
9
17
|
private
|
10
18
|
|
11
|
-
def
|
12
|
-
|
19
|
+
def test_files
|
20
|
+
list_files(Uncov.configuration.relevant_tests)
|
13
21
|
end
|
14
22
|
|
15
|
-
def
|
23
|
+
def list_files(glob)
|
24
|
+
Dir.glob(glob, Uncov::Configuration::FILE_MATCH_FLAGS).select { |f| File.file?(f) }
|
25
|
+
end
|
16
26
|
|
17
27
|
def read_lines(file_name)
|
18
28
|
File.readlines(file_name).each_with_index.to_h { |line, line_index| [line_index + 1, line.rstrip] }
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# wrap finder results to have the same interface as finder
|
4
|
+
class Uncov::Finder::Files
|
5
|
+
attr_reader :files
|
6
|
+
|
7
|
+
def initialize(files)
|
8
|
+
@files = files
|
9
|
+
end
|
10
|
+
|
11
|
+
def file?(file_name)
|
12
|
+
@files.key?(file_name)
|
13
|
+
end
|
14
|
+
|
15
|
+
def file_names
|
16
|
+
@files.keys
|
17
|
+
end
|
18
|
+
|
19
|
+
def lines(file_name)
|
20
|
+
@files[file_name] || {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def line(file_name, line_number)
|
24
|
+
@files.dig(file_name, line_number)
|
25
|
+
end
|
26
|
+
|
27
|
+
def line?(file_name, line_number)
|
28
|
+
lines(file_name)&.key?(line_number)
|
29
|
+
end
|
30
|
+
end
|
data/lib/uncov/finder/git.rb
CHANGED
@@ -3,14 +3,34 @@
|
|
3
3
|
require_relative 'git_base'
|
4
4
|
|
5
5
|
# collect list of files stored in git
|
6
|
-
|
7
|
-
|
8
|
-
include Uncov::Finder::GitBase
|
6
|
+
class Uncov::Finder::Git
|
7
|
+
include Uncov::Finder::GitBase
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
def code_files
|
10
|
+
cache(:code_files) do
|
11
|
+
all_file_names.filter_map do |file_name|
|
12
|
+
[file_name, true] if relevant_code_file?(file_name)
|
13
13
|
end.to_h
|
14
14
|
end
|
15
15
|
end
|
16
|
+
|
17
|
+
def simplecov_trigger_files
|
18
|
+
code_files.keys + test_files
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def test_files
|
24
|
+
cache(:test_files) do
|
25
|
+
all_file_names.select do |file_name|
|
26
|
+
relevant_test_file?(file_name)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def all_file_names
|
32
|
+
cache(:all_files) do
|
33
|
+
open_repo.ls_files.keys
|
34
|
+
end
|
35
|
+
end
|
16
36
|
end
|
@@ -4,14 +4,22 @@ require 'git'
|
|
4
4
|
|
5
5
|
# common parts for git finders
|
6
6
|
module Uncov::Finder::GitBase
|
7
|
+
include Uncov::Cache
|
8
|
+
|
7
9
|
protected
|
8
10
|
|
9
|
-
def
|
11
|
+
def relevant_code_file?(path)
|
10
12
|
File.fnmatch?(Uncov.configuration.relevant_files, path, Uncov::Configuration::FILE_MATCH_FLAGS)
|
11
13
|
end
|
12
14
|
|
15
|
+
def relevant_test_file?(path)
|
16
|
+
File.fnmatch?(Uncov.configuration.relevant_tests, path, Uncov::Configuration::FILE_MATCH_FLAGS)
|
17
|
+
end
|
18
|
+
|
13
19
|
def open_repo
|
14
|
-
|
20
|
+
cache(:repo) do
|
21
|
+
::Git.open('.')
|
22
|
+
end
|
15
23
|
rescue ArgumentError => e
|
16
24
|
raise Uncov::NotGitRepoError, Uncov.configuration.path if e.message.end_with?(' is not in a git working tree')
|
17
25
|
|