Class: Henitai::SourceFileSelection
- Inherits:
-
Object
- Object
- Henitai::SourceFileSelection
- Defined in:
- lib/henitai/source_file_selection.rb,
sig/henitai.rbs
Overview
Resolves which source files a run mutates: everything under includes:,
minus anything matched by excludes:, optionally narrowed to what changed
since a git ref.
Excludes are absolute, not a tiebreak: an excluded file (a standalone entry
point that cannot be mutation-tested in-process, say) stays excluded even
when it is the only thing that changed. Both stages are filters over the
same list, so they commute — excludes run first only to keep the
per-test-coverage lookups in filter_changed off files that are already
out of scope.
Instance Method Summary collapse
- #call ⇒ Array[String]
-
#changed_paths_since ⇒ Array[String]
Committed changes since the ref plus the current working tree (tracked dirty and untracked files): the working tree is what gets tested, so it is always part of "changed since REF".
-
#covered_sources_for_changed_tests(changed_paths) ⇒ Array[String]
Changed test files select the source files they cover, so an edited test re-tests the subjects it can kill.
- #excluded_source_files ⇒ Array[String]
- #filter_changed(files) ⇒ Array[String]
- #included_source_files ⇒ Array[String]
-
#initialize(config:, since:, git_diff_analyzer:, per_test_coverage:) ⇒ SourceFileSelection
constructor
A new instance of SourceFileSelection.
- #normalize_path(path) ⇒ String
-
#reject_excluded(files) ⇒ Array[String]
Drops files matched by any
excludes:glob.
Constructor Details
#initialize(config:, since:, git_diff_analyzer:, per_test_coverage:) ⇒ SourceFileSelection
Returns a new instance of SourceFileSelection.
15 16 17 18 19 20 |
# File 'lib/henitai/source_file_selection.rb', line 15 def initialize(config:, since:, git_diff_analyzer:, per_test_coverage:) @config = config @since = since @git_diff_analyzer = git_diff_analyzer @per_test_coverage = per_test_coverage end |
Instance Method Details
#call ⇒ Array[String]
22 23 24 |
# File 'lib/henitai/source_file_selection.rb', line 22 def call filter_changed(reject_excluded(included_source_files)) end |
#changed_paths_since ⇒ Array[String]
Committed changes since the ref plus the current working tree (tracked dirty and untracked files): the working tree is what gets tested, so it is always part of "changed since REF".
60 61 62 63 |
# File 'lib/henitai/source_file_selection.rb', line 60 def changed_paths_since @git_diff_analyzer.changed_files(from: @since, to: "HEAD") + @git_diff_analyzer.working_tree_changed_files end |
#covered_sources_for_changed_tests(changed_paths) ⇒ Array[String]
Changed test files select the source files they cover, so an edited test re-tests the subjects it can kill. Uses the per-test map from the previous run — Gate 1 runs before this run's bootstrap finishes.
68 69 70 71 72 |
# File 'lib/henitai/source_file_selection.rb', line 68 def covered_sources_for_changed_tests(changed_paths) changed_paths .flat_map { |path| @per_test_coverage.source_files_covered_by(path) } .map { |path| normalize_path(path) } end |
#excluded_source_files ⇒ Array[String]
51 52 53 54 55 |
# File 'lib/henitai/source_file_selection.rb', line 51 def excluded_source_files Array(@config.excludes) .flat_map { |pattern| Dir.glob(pattern) } .map { |path| normalize_path(path) } end |
#filter_changed(files) ⇒ Array[String]
41 42 43 44 45 46 47 |
# File 'lib/henitai/source_file_selection.rb', line 41 def filter_changed(files) return files unless @since changed = changed_paths_since.map { |path| normalize_path(path) } changed += covered_sources_for_changed_tests(changed) files.select { |path| changed.include?(normalize_path(path)) } end |
#included_source_files ⇒ Array[String]
26 27 28 29 30 |
# File 'lib/henitai/source_file_selection.rb', line 26 def included_source_files Array(@config.includes).flat_map do |include_path| Dir.glob(File.join(include_path, "**", "*.rb")) end.uniq end |
#normalize_path(path) ⇒ String
74 |
# File 'lib/henitai/source_file_selection.rb', line 74 def normalize_path(path) = File.(path) |
#reject_excluded(files) ⇒ Array[String]
Drops files matched by any excludes: glob. Compared as expanded paths so
a relative glob and an absolute candidate still match.
34 35 36 37 38 39 |
# File 'lib/henitai/source_file_selection.rb', line 34 def reject_excluded(files) excluded = excluded_source_files return files if excluded.empty? files.reject { |path| excluded.include?(normalize_path(path)) } end |