crystalball 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|