crystalball 0.5.0 → 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/.gitignore +4 -1
- data/.rubocop.yml +4 -0
- data/.travis.yml +1 -1
- data/CHANGELOG.md +18 -0
- data/LICENSE +22 -674
- data/README.md +13 -158
- data/crystalball.gemspec +6 -2
- data/docs/img/favicon.ico +0 -0
- data/docs/img/logo.png +0 -0
- data/docs/index.md +44 -0
- data/docs/map_generators.md +149 -0
- data/docs/predictors.md +75 -0
- data/docs/runner.md +24 -0
- data/lib/crystalball.rb +8 -3
- data/lib/crystalball/active_record.rb +4 -0
- data/lib/crystalball/example_group_map.rb +19 -0
- data/lib/crystalball/execution_map.rb +17 -16
- data/lib/crystalball/extensions/git.rb +4 -0
- data/lib/crystalball/extensions/git/base.rb +14 -0
- data/lib/crystalball/extensions/git/lib.rb +18 -0
- data/lib/crystalball/factory_bot.rb +3 -0
- data/lib/crystalball/git_repo.rb +2 -7
- data/lib/crystalball/logging.rb +51 -0
- data/lib/crystalball/map_generator.rb +5 -7
- data/lib/crystalball/map_generator/allocated_objects_strategy.rb +6 -5
- data/lib/crystalball/map_generator/allocated_objects_strategy/object_tracker.rb +1 -0
- data/lib/crystalball/map_generator/base_strategy.rb +5 -4
- data/lib/crystalball/map_generator/configuration.rb +1 -1
- data/lib/crystalball/map_generator/coverage_strategy.rb +6 -5
- data/lib/crystalball/map_generator/described_class_strategy.rb +5 -5
- data/lib/crystalball/map_generator/factory_bot_strategy.rb +59 -0
- data/lib/crystalball/map_generator/factory_bot_strategy/dsl_patch.rb +40 -0
- data/lib/crystalball/map_generator/factory_bot_strategy/dsl_patch/factory_path_fetcher.rb +30 -0
- data/lib/crystalball/map_generator/factory_bot_strategy/factory_gem_loader.rb +27 -0
- data/lib/crystalball/map_generator/factory_bot_strategy/factory_runner_patch.rb +25 -0
- data/lib/crystalball/map_generator/parser_strategy.rb +60 -0
- data/lib/crystalball/map_generator/parser_strategy/processor.rb +129 -0
- data/lib/crystalball/map_generator/strategies_collection.rb +9 -9
- data/lib/crystalball/map_storage/yaml_storage.rb +7 -6
- data/lib/crystalball/prediction.rb +12 -11
- data/lib/crystalball/predictor.rb +7 -5
- data/lib/crystalball/predictor/associated_specs.rb +9 -4
- data/lib/crystalball/predictor/helpers/affected_example_groups_detector.rb +20 -0
- data/lib/crystalball/predictor/helpers/path_formatter.rb +18 -0
- data/lib/crystalball/predictor/modified_execution_paths.rb +11 -5
- data/lib/crystalball/predictor/modified_specs.rb +8 -2
- data/lib/crystalball/predictor/modified_support_specs.rb +39 -0
- data/lib/crystalball/predictor/strategy.rb +16 -0
- data/lib/crystalball/predictor_evaluator.rb +1 -1
- data/lib/crystalball/rails.rb +1 -0
- data/lib/crystalball/rails/helpers/base_schema_parser.rb +51 -0
- data/lib/crystalball/rails/helpers/schema_definition_parser.rb +36 -0
- data/lib/crystalball/rails/helpers/schema_definition_parser/active_record.rb +21 -0
- data/lib/crystalball/rails/helpers/schema_definition_parser/table_content_parser.rb +27 -0
- data/lib/crystalball/rails/map_generator/action_view_strategy.rb +5 -5
- data/lib/crystalball/rails/map_generator/action_view_strategy/patch.rb +1 -1
- data/lib/crystalball/rails/map_generator/i18n_strategy.rb +5 -5
- data/lib/crystalball/rails/map_generator/i18n_strategy/simple_patch.rb +1 -0
- data/lib/crystalball/rails/predictor/modified_schema.rb +81 -0
- data/lib/crystalball/rails/tables_map.rb +53 -0
- data/lib/crystalball/rails/tables_map_generator.rb +84 -0
- data/lib/crystalball/rails/tables_map_generator/configuration.rb +39 -0
- data/lib/crystalball/rspec/filtering.rb +52 -0
- data/lib/crystalball/rspec/prediction_builder.rb +21 -11
- data/lib/crystalball/rspec/prediction_pruning.rb +56 -0
- data/lib/crystalball/rspec/prediction_pruning/examples_pruner.rb +70 -0
- data/lib/crystalball/rspec/runner.rb +39 -27
- data/lib/crystalball/rspec/runner/configuration.rb +24 -14
- data/lib/crystalball/rspec/standard_prediction_builder.rb +17 -0
- data/lib/crystalball/source_diff.rb +12 -2
- data/lib/crystalball/source_diff/file_diff.rb +1 -1
- data/lib/crystalball/source_diff/formatting_checker.rb +50 -0
- data/lib/crystalball/version.rb +1 -1
- data/mkdocs.yml +23 -0
- metadata +102 -7
- data/lib/crystalball/case_map.rb +0 -19
- data/lib/crystalball/simple_predictor.rb +0 -18
@@ -1,11 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'crystalball/predictor/strategy'
|
4
|
+
|
3
5
|
module Crystalball
|
4
6
|
class Predictor
|
5
7
|
# Used with `predictor.use Crystalball::Predictor::AssociatedSpecs.new(from: %r{models/(.*).rb}, to: "./spec/models/%s_spec.rb")`.
|
6
8
|
# When used will look for files matched to `from` regex and use captures to fill `to` string to
|
7
9
|
# get paths of proper specs
|
8
10
|
class AssociatedSpecs
|
11
|
+
include Strategy
|
12
|
+
|
9
13
|
# @param [Regexp] from - regular expression to match specific files and get proper captures
|
10
14
|
# @param [String] to - string in sprintf format to get proper files using captures of regexp
|
11
15
|
def initialize(from:, to:)
|
@@ -13,14 +17,15 @@ module Crystalball
|
|
13
17
|
@to = to
|
14
18
|
end
|
15
19
|
|
16
|
-
# This strategy does not depend on a previously generated
|
20
|
+
# This strategy does not depend on a previously generated example group map.
|
17
21
|
# It uses the defined regex rules to infer which specs to run.
|
18
22
|
# @param [Crystalball::SourceDiff] diff - the diff from which to predict
|
19
23
|
# which specs should run
|
20
24
|
# @return [Array<String>] the spec paths associated with the changes
|
21
|
-
def call(diff,
|
22
|
-
|
23
|
-
|
25
|
+
def call(diff, _map)
|
26
|
+
super do
|
27
|
+
diff.map(&:relative_path).grep(from).map { |source_file_path| to % captures(source_file_path) }
|
28
|
+
end
|
24
29
|
end
|
25
30
|
|
26
31
|
private
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Crystalball
|
4
|
+
class Predictor
|
5
|
+
module Helpers
|
6
|
+
# Helper module to fetch example groups affected by given list of changed files
|
7
|
+
module AffectedExampleGroupsDetector
|
8
|
+
# Fetch examples affected by given list of files
|
9
|
+
# @param [Array<String>] files - list of files
|
10
|
+
# @param [Crystalball::ExecutionMap] map - execution map with examples
|
11
|
+
# @return [Array<String>] list of affected examples
|
12
|
+
def detect_examples(files, map)
|
13
|
+
map.example_groups.map do |uid, example_group_map|
|
14
|
+
uid if files.any? { |file| example_group_map.include?(file) }
|
15
|
+
end.compact
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Crystalball
|
4
|
+
class Predictor
|
5
|
+
module Helpers
|
6
|
+
# Helper module for converting relative path to RSpec format
|
7
|
+
module PathFormatter
|
8
|
+
def format_paths(paths)
|
9
|
+
paths.map { |path| format_path(path) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def format_path(path)
|
13
|
+
path.start_with?('./') ? path : "./#{path}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -1,20 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'crystalball/predictor/strategy'
|
4
|
+
require 'crystalball/predictor/helpers/affected_example_groups_detector'
|
5
|
+
|
3
6
|
module Crystalball
|
4
7
|
class Predictor
|
5
8
|
# Used with `predictor.use Crystalball::Predictor::ModifiedExecutionPaths.new`. When used will check the map which
|
6
9
|
# specs depend on which files and will return only those specs which depend on files modified since last time map
|
7
10
|
# was generated.
|
8
11
|
class ModifiedExecutionPaths
|
12
|
+
include Helpers::AffectedExampleGroupsDetector
|
13
|
+
include Strategy
|
14
|
+
|
9
15
|
# @param [Crystalball::SourceDiff] diff - the diff from which to predict
|
10
16
|
# which specs should run
|
11
|
-
# @param [Crystalball::
|
12
|
-
# examples and
|
17
|
+
# @param [Crystalball::ExampleGroupMap] map - the map with the relations of
|
18
|
+
# examples and used files
|
13
19
|
# @return [Array<String>] the spec paths associated with the changes
|
14
20
|
def call(diff, map)
|
15
|
-
|
16
|
-
|
17
|
-
end
|
21
|
+
super do
|
22
|
+
detect_examples(diff.map(&:relative_path), map)
|
23
|
+
end
|
18
24
|
end
|
19
25
|
end
|
20
26
|
end
|
@@ -1,22 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'crystalball/predictor/strategy'
|
4
|
+
|
3
5
|
module Crystalball
|
4
6
|
class Predictor
|
5
7
|
# Used with `predictor.use Crystalball::Predictor::ModifiedSpecs.new`. Will find files that match spec regexp and
|
6
8
|
# return all new or modified files. You can specify spec regexp using first parameter to `#initialize`.
|
7
9
|
class ModifiedSpecs
|
10
|
+
include Strategy
|
11
|
+
|
8
12
|
# @param [Regexp] spec_pattern - regexp to filter specs files
|
9
13
|
def initialize(spec_pattern = %r{spec/.*_spec\.rb\z})
|
10
14
|
@spec_pattern = spec_pattern
|
11
15
|
end
|
12
16
|
|
13
|
-
# This strategy does not depend on a previously generated
|
17
|
+
# This strategy does not depend on a previously generated example group map.
|
14
18
|
# It uses the spec pattern to determine which specs should run.
|
15
19
|
# @param [Crystalball::SourceDiff] diff - the diff from which to predict
|
16
20
|
# which specs should run
|
17
21
|
# @return [Array<String>] the spec paths associated with the changes
|
18
22
|
def call(diff, _)
|
19
|
-
|
23
|
+
super do
|
24
|
+
diff.reject(&:deleted?).map(&:new_relative_path).grep(spec_pattern)
|
25
|
+
end
|
20
26
|
end
|
21
27
|
|
22
28
|
private
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'crystalball/predictor/strategy'
|
4
|
+
require 'crystalball/predictor/helpers/affected_example_groups_detector'
|
5
|
+
|
6
|
+
module Crystalball
|
7
|
+
class Predictor
|
8
|
+
# Used with `predictor.use Crystalball::Predictor::ModifiedSupportSpecs.new`. Will find files that match passed regexp and
|
9
|
+
# return full spec files which uses matched support spec files. Perfectly works for shared_context and shared_examples.
|
10
|
+
class ModifiedSupportSpecs
|
11
|
+
include Strategy
|
12
|
+
include Helpers::AffectedExampleGroupsDetector
|
13
|
+
|
14
|
+
# @param [Regexp] support_spec_pattern - regexp to filter support specs files
|
15
|
+
def initialize(support_spec_pattern = %r{spec/support/.*\.rb\z})
|
16
|
+
@support_spec_pattern = support_spec_pattern
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param [Crystalball::SourceDiff] diff - the diff from which to predict
|
20
|
+
# which specs should run
|
21
|
+
# @param [Crystalball::ExampleGroupMap] map - the map with the relations of
|
22
|
+
# examples and used files
|
23
|
+
# @return [Array<String>] the spec paths associated with the changes
|
24
|
+
def call(diff, map)
|
25
|
+
super do
|
26
|
+
changed_support_files = diff.map(&:relative_path).grep(support_spec_pattern)
|
27
|
+
|
28
|
+
examples = detect_examples(changed_support_files, map)
|
29
|
+
|
30
|
+
examples.map { |e| e.to_s.split('[').first }.uniq
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
attr_reader :support_spec_pattern
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'crystalball/predictor/helpers/path_formatter'
|
4
|
+
|
5
|
+
module Crystalball
|
6
|
+
class Predictor
|
7
|
+
# Base module to include in any strategy. Provides output formatting similar to RSpec
|
8
|
+
module Strategy
|
9
|
+
include Helpers::PathFormatter
|
10
|
+
|
11
|
+
def call(*)
|
12
|
+
format_paths(yield)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -39,7 +39,7 @@ module Crystalball
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def prediction_size
|
42
|
-
@prediction_size ||= predictor.map.
|
42
|
+
@prediction_size ||= predictor.map.example_groups.keys.select { |example| prediction.any? { |p| example.include?(p) } }.size
|
43
43
|
end
|
44
44
|
|
45
45
|
def map_size
|
data/lib/crystalball/rails.rb
CHANGED
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Crystalball
|
4
|
+
module Rails
|
5
|
+
module Helpers
|
6
|
+
# Interface for schema parsers
|
7
|
+
module BaseSchemaParser
|
8
|
+
def self.parse(*_)
|
9
|
+
raise NotImplementedError
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [Hash] stored info about all method calls which ended in #method_missing
|
13
|
+
attr_accessor :hash
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@hash = {}
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# Store info about call in hash. First argument of method call used as a key
|
22
|
+
def method_missing(method_name, *args, &block)
|
23
|
+
name = args.shift
|
24
|
+
add_to_hash(name, options: [method_name] + args)
|
25
|
+
|
26
|
+
new_parser = self.class.new
|
27
|
+
add_to_hash(name, content: new_parser.instance_exec(&block)) if block
|
28
|
+
add_to_hash(name, content: new_parser.hash)
|
29
|
+
new_parser
|
30
|
+
end
|
31
|
+
|
32
|
+
def respond_to_missing?(*_)
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
def add_to_hash(name, options: nil, content: nil)
|
37
|
+
hash[name] ||= {}
|
38
|
+
add_optional(name, :options, options)
|
39
|
+
add_optional(name, :content, content)
|
40
|
+
end
|
41
|
+
|
42
|
+
def add_optional(name, key, value)
|
43
|
+
return unless value
|
44
|
+
|
45
|
+
hash[name][key] ||= []
|
46
|
+
hash[name][key] << value
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'crystalball/rails/helpers/base_schema_parser'
|
4
|
+
require 'crystalball/rails/helpers/schema_definition_parser/active_record'
|
5
|
+
require 'crystalball/rails/helpers/schema_definition_parser/table_content_parser'
|
6
|
+
|
7
|
+
module Crystalball
|
8
|
+
module Rails
|
9
|
+
module Helpers
|
10
|
+
# Class used to parse ActiveRecord::Schema definition and provide hash representation
|
11
|
+
class SchemaDefinitionParser
|
12
|
+
include BaseSchemaParser
|
13
|
+
|
14
|
+
# Parse schema content
|
15
|
+
# @param [String] schema - schema file content
|
16
|
+
# @return [Hash] hash representation of schema
|
17
|
+
def self.parse(schema)
|
18
|
+
return {} if schema&.empty?
|
19
|
+
|
20
|
+
new.instance_eval(schema)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def create_table(table_name, *options, &block)
|
26
|
+
add_to_hash(table_name, options: ['create_table'] + options, content: TableContentParser.parse(&block))
|
27
|
+
end
|
28
|
+
|
29
|
+
def add_foreign_key(table1, table2, *options)
|
30
|
+
add_to_hash(table1, options: ['add_foreign_key', table2] + options)
|
31
|
+
add_to_hash(table2, options: ['add_foreign_key', table1] + options) if table1 != table2
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Crystalball
|
4
|
+
module Rails
|
5
|
+
module Helpers
|
6
|
+
class SchemaDefinitionParser
|
7
|
+
# This mock will be used during SchemaDefinitionParser.parse
|
8
|
+
module ActiveRecord
|
9
|
+
# A simple mock to read definition of schema
|
10
|
+
class Schema
|
11
|
+
def self.define(*_args, &block)
|
12
|
+
collector = SchemaDefinitionParser.new
|
13
|
+
collector.instance_exec(collector, &block)
|
14
|
+
collector.hash
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'crystalball/rails/helpers/base_schema_parser'
|
4
|
+
|
5
|
+
module Crystalball
|
6
|
+
module Rails
|
7
|
+
module Helpers
|
8
|
+
class SchemaDefinitionParser
|
9
|
+
# Class used to parse ActiveRecord::Schema create_table definition and provide hash representation
|
10
|
+
class TableContentParser
|
11
|
+
include BaseSchemaParser
|
12
|
+
|
13
|
+
# Parse create_table definition of schema
|
14
|
+
# @param [Proc] block - block for create_table definition
|
15
|
+
# @return [Hash] hash representation of table definition
|
16
|
+
def self.parse(&block)
|
17
|
+
return {} unless block
|
18
|
+
|
19
|
+
collector = new
|
20
|
+
collector.instance_exec(collector, &block)
|
21
|
+
collector.hash
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -33,12 +33,12 @@ module Crystalball
|
|
33
33
|
Patch.revert!
|
34
34
|
end
|
35
35
|
|
36
|
-
# Adds views related to the spec to the
|
37
|
-
# @param [Crystalball::
|
38
|
-
def call(
|
36
|
+
# Adds views related to the spec to the example group map
|
37
|
+
# @param [Crystalball::ExampleGroupMap] example_group_map - object holding example metadata and used files
|
38
|
+
def call(example_group_map, _)
|
39
39
|
self.class.reset_views
|
40
|
-
yield
|
41
|
-
|
40
|
+
yield example_group_map
|
41
|
+
example_group_map.push(*filter(self.class.views))
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
@@ -9,7 +9,7 @@ module Crystalball
|
|
9
9
|
# Module to add new patched `compile!` method to ActionView::Template
|
10
10
|
module Patch
|
11
11
|
class << self
|
12
|
-
# Patches `ActionView::Template#compile!`. Renames original `compile!` to `
|
12
|
+
# Patches `ActionView::Template#compile!`. Renames original `compile!` to `cb_original_compile!` and
|
13
13
|
# replaces it with custom one
|
14
14
|
def apply!
|
15
15
|
::ActionView::Template.class_eval do
|
@@ -34,12 +34,12 @@ module Crystalball
|
|
34
34
|
SimplePatch.revert!
|
35
35
|
end
|
36
36
|
|
37
|
-
# Adds to the
|
38
|
-
# @param [Crystalball::
|
39
|
-
def call(
|
37
|
+
# Adds to the example group map the locale files used by the example
|
38
|
+
# @param [Crystalball::ExampleGroupMap] example_group_map - object holding example metadata and used files
|
39
|
+
def call(example_group_map, _)
|
40
40
|
self.class.reset_locale_files
|
41
|
-
yield
|
42
|
-
|
41
|
+
yield example_group_map
|
42
|
+
example_group_map.push(*filter(self.class.locale_files.compact))
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'crystalball/rails/helpers/schema_definition_parser'
|
4
|
+
require 'crystalball/predictor/helpers/affected_example_groups_detector'
|
5
|
+
|
6
|
+
module Crystalball
|
7
|
+
module Rails
|
8
|
+
class Predictor
|
9
|
+
# Used with `predictor.use Crystalball::Rails::Predictor::ModifiedSchema.new(tables_map_path:)`.
|
10
|
+
# When used will check db/schema.rb for changes and add specs which depend on files affected
|
11
|
+
# by changed tables
|
12
|
+
class ModifiedSchema
|
13
|
+
include ::Crystalball::Predictor::Helpers::AffectedExampleGroupsDetector
|
14
|
+
SCHEMA_PATH = 'db/schema.rb'
|
15
|
+
|
16
|
+
attr_reader :tables_map_path
|
17
|
+
|
18
|
+
# @param [String] tables_map_path - path to generated TablesMap
|
19
|
+
def initialize(tables_map_path:)
|
20
|
+
@tables_map_path = tables_map_path
|
21
|
+
end
|
22
|
+
|
23
|
+
# @param [Crystalball::SourceDiff] diff - the diff from which to predict
|
24
|
+
# which specs should run
|
25
|
+
# @param [Crystalball::ExecutionMap] map - the map with the relations of
|
26
|
+
# examples and used files
|
27
|
+
# @return [Array<String>] the spec paths associated with the changes
|
28
|
+
def call(diff, map)
|
29
|
+
return [] if schema_diff(diff).nil?
|
30
|
+
|
31
|
+
old_schema = old_schema(diff)
|
32
|
+
new_schema = new_schema(diff)
|
33
|
+
|
34
|
+
changed_tables = changed_tables(old_schema, new_schema)
|
35
|
+
|
36
|
+
files = changed_tables.flat_map do |table_name|
|
37
|
+
files = tables_map[table_name]
|
38
|
+
Crystalball.log :warn, "There are no model files for changed table `#{table_name}`. Check https://github.com/toptal/crystalball#warning for detailed description" unless files&.any?
|
39
|
+
files
|
40
|
+
end.compact
|
41
|
+
detect_examples(files, map)
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [Crystalball::Rails::TablesMap]
|
45
|
+
def tables_map
|
46
|
+
@tables_map ||= MapStorage::YAMLStorage.load(Pathname(tables_map_path))
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def schema_diff(diff)
|
52
|
+
diff.find { |file_diff| [SCHEMA_PATH, "./#{SCHEMA_PATH}"].include? file_diff.relative_path }
|
53
|
+
end
|
54
|
+
|
55
|
+
def old_schema(diff)
|
56
|
+
old_schema_contents = schema_content(diff.repository, diff.from)
|
57
|
+
Crystalball::Rails::Helpers::SchemaDefinitionParser.parse(old_schema_contents)
|
58
|
+
end
|
59
|
+
|
60
|
+
def new_schema(diff)
|
61
|
+
new_schema_contents = schema_content(diff.repository, diff.to)
|
62
|
+
Crystalball::Rails::Helpers::SchemaDefinitionParser.parse(new_schema_contents)
|
63
|
+
end
|
64
|
+
|
65
|
+
def schema_content(repository, revision)
|
66
|
+
if revision
|
67
|
+
repository.lib.show(revision, SCHEMA_PATH)
|
68
|
+
else
|
69
|
+
File.read(File.join(repository.dir.path, SCHEMA_PATH))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def changed_tables(schema1, schema2)
|
74
|
+
schema1.map do |table_name, body|
|
75
|
+
table_name if schema2[table_name] != body
|
76
|
+
end.compact
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|