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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 60ed1a2dd6520f9df75c5cc77e4b8b7b59d7ea61c6ae16c2e1ecad8bf86ae17a
4
- data.tar.gz: 73bc05c3c969b1c8f2e7853f79aa96c2e793958c06bb0b0b3f4f6d03588501ca
3
+ metadata.gz: fc5eb3c1149eba5de56dd2bd43a4bf9a450abc25689456ef9290da0bb903b657
4
+ data.tar.gz: '08567ab62f909c0b8ebdf9f8bc8793edcb0e96e77408b10a5249da61cab7e42d'
5
5
  SHA512:
6
- metadata.gz: 860d74da20e5c28b665829510cfc0e2e0aef47f1ba179a7e6d4fd0038740bdbe8b60b6ae471e15c1677d06a6fea62609ec543328034a5de58d55249d7dcee713
7
- data.tar.gz: '0927a3a3c86100b376d92766ff6f7311797bb6345407948e418a4366a40231f38db1b9486934f1278f36b2977407fb5cf36935cac89a98f9841be991e504aa47'
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 TYPE Report type to generate, one_of: "diff_lines"(default)
40
- -o, --output-format FORMAT Output format, one_of: "terminal"(default)
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 Relevant files shell filename globing: https://ruby-doc.org/core-3.1.1/File.html#method-c-fnmatch, default: "{{bin,exe,exec}/*,{app,lib}/**/*.{rake,rb},Rakefile}"
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
- uncov 0.4.2 by Michal Papis <mpapis@gmail.com>
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 "Found #{report.uncovered_files.size} files with uncovered changes:".yellow
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
- puts
20
- puts format('Overall coverage of changes: %.2f%%', report.coverage).yellow
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.uncovered_files.each do |file_coverage|
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.covered_lines.count,
44
- relevant_lines: file_coverage.relevant_lines.count
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.build
9
+ report = Uncov::Report.generate
10
10
  Uncov::Formatter.output(report)
11
- !report.uncov?
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, :allowed_values, :value_parse, :value
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
@@ -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 type to generate', options: ['-r', '--report TYPE'], default: 'diff_lines', allowed_values: Uncov::Report.types
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: 'terminal', allowed_values: Uncov::Formatter.formats
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', 'Relevant files shell filename globing: https://ruby-doc.org/core-3.1.1/File.html#method-c-fnmatch',
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 options = @options ||= {}
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 files = all_files.to_h { |file_name| [file_name, lines_proc(file_name)] }
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 all_files
12
- Dir.glob(Uncov.configuration.relevant_files, Uncov::Configuration::FILE_MATCH_FLAGS).select { |f| File.file?(f) }
19
+ def test_files
20
+ list_files(Uncov.configuration.relevant_tests)
13
21
  end
14
22
 
15
- def lines_proc(file_name) = -> { cache(file_name) { read_lines(file_name) } }
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
@@ -3,14 +3,34 @@
3
3
  require_relative 'git_base'
4
4
 
5
5
  # collect list of files stored in git
6
- module Uncov::Finder::Git
7
- class << self
8
- include Uncov::Finder::GitBase
6
+ class Uncov::Finder::Git
7
+ include Uncov::Finder::GitBase
9
8
 
10
- def files
11
- open_repo.ls_files.keys.filter_map do |file_name|
12
- [file_name, true] if relevant_file?(file_name)
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 relevant_file?(path)
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
- ::Git.open('.')
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