ree 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +13 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +41 -0
- data/LICENSE.txt +21 -0
- data/README.md +474 -0
- data/Rakefile +8 -0
- data/bin/console +8 -0
- data/bin/setup +8 -0
- data/exe/ree +264 -0
- data/lib/ree/args.rb +34 -0
- data/lib/ree/bean_dsl.rb +24 -0
- data/lib/ree/cli/generate_package.rb +18 -0
- data/lib/ree/cli/generate_package_schema.rb +54 -0
- data/lib/ree/cli/generate_packages_schema.rb +17 -0
- data/lib/ree/cli/generate_template.rb +20 -0
- data/lib/ree/cli/init.rb +22 -0
- data/lib/ree/cli/spec_runner.rb +184 -0
- data/lib/ree/cli.rb +12 -0
- data/lib/ree/container.rb +67 -0
- data/lib/ree/contracts/arg_contracts/any.rb +15 -0
- data/lib/ree/contracts/arg_contracts/array_of.rb +52 -0
- data/lib/ree/contracts/arg_contracts/block.rb +15 -0
- data/lib/ree/contracts/arg_contracts/bool.rb +21 -0
- data/lib/ree/contracts/arg_contracts/eq.rb +28 -0
- data/lib/ree/contracts/arg_contracts/exactly.rb +28 -0
- data/lib/ree/contracts/arg_contracts/hash_of.rb +59 -0
- data/lib/ree/contracts/arg_contracts/ksplat.rb +141 -0
- data/lib/ree/contracts/arg_contracts/kwargs.rb +22 -0
- data/lib/ree/contracts/arg_contracts/nilor.rb +16 -0
- data/lib/ree/contracts/arg_contracts/none.rb +15 -0
- data/lib/ree/contracts/arg_contracts/optblock.rb +11 -0
- data/lib/ree/contracts/arg_contracts/or.rb +30 -0
- data/lib/ree/contracts/arg_contracts/range_of.rb +51 -0
- data/lib/ree/contracts/arg_contracts/set_of.rb +54 -0
- data/lib/ree/contracts/arg_contracts/splat.rb +297 -0
- data/lib/ree/contracts/arg_contracts/splat_of.rb +64 -0
- data/lib/ree/contracts/arg_contracts/squarable.rb +11 -0
- data/lib/ree/contracts/arg_contracts/subclass_of.rb +28 -0
- data/lib/ree/contracts/arg_contracts.rb +29 -0
- data/lib/ree/contracts/called_args_validator.rb +291 -0
- data/lib/ree/contracts/contract_definition.rb +142 -0
- data/lib/ree/contracts/contractable.rb +34 -0
- data/lib/ree/contracts/core.rb +17 -0
- data/lib/ree/contracts/engine.rb +71 -0
- data/lib/ree/contracts/engine_proxy.rb +13 -0
- data/lib/ree/contracts/errors/bad_contract_error.rb +4 -0
- data/lib/ree/contracts/errors/contract_error.rb +4 -0
- data/lib/ree/contracts/errors/error.rb +4 -0
- data/lib/ree/contracts/errors/return_contract_error.rb +4 -0
- data/lib/ree/contracts/method_decorator.rb +158 -0
- data/lib/ree/contracts/truncatable.rb +9 -0
- data/lib/ree/contracts/utils.rb +9 -0
- data/lib/ree/contracts/validators/array_validator.rb +51 -0
- data/lib/ree/contracts/validators/base_validator.rb +27 -0
- data/lib/ree/contracts/validators/class_validator.rb +17 -0
- data/lib/ree/contracts/validators/default_validator.rb +20 -0
- data/lib/ree/contracts/validators/hash_validator.rb +100 -0
- data/lib/ree/contracts/validators/proc_validator.rb +17 -0
- data/lib/ree/contracts/validators/range_validator.rb +17 -0
- data/lib/ree/contracts/validators/regexp_validator.rb +17 -0
- data/lib/ree/contracts/validators/valid_validator.rb +28 -0
- data/lib/ree/contracts/validators.rb +42 -0
- data/lib/ree/contracts.rb +45 -0
- data/lib/ree/core/link_validator.rb +42 -0
- data/lib/ree/core/object.rb +132 -0
- data/lib/ree/core/object_error.rb +9 -0
- data/lib/ree/core/object_link.rb +21 -0
- data/lib/ree/core/object_schema.rb +47 -0
- data/lib/ree/core/object_schema_builder.rb +110 -0
- data/lib/ree/core/package.rb +177 -0
- data/lib/ree/core/package_dep.rb +9 -0
- data/lib/ree/core/package_env_var.rb +12 -0
- data/lib/ree/core/package_loader.rb +95 -0
- data/lib/ree/core/package_schema.rb +27 -0
- data/lib/ree/core/package_schema_builder.rb +53 -0
- data/lib/ree/core/package_schema_loader.rb +170 -0
- data/lib/ree/core/packages_detector.rb +43 -0
- data/lib/ree/core/packages_schema.rb +19 -0
- data/lib/ree/core/packages_schema_builder.rb +50 -0
- data/lib/ree/core/packages_schema_loader.rb +95 -0
- data/lib/ree/core/packages_schema_locator.rb +27 -0
- data/lib/ree/core/packages_store.rb +32 -0
- data/lib/ree/core/path_helper.rb +104 -0
- data/lib/ree/dsl/build_package_dsl.rb +155 -0
- data/lib/ree/dsl/domain_error.rb +4 -0
- data/lib/ree/dsl/error_builder.rb +39 -0
- data/lib/ree/dsl/error_dsl.rb +27 -0
- data/lib/ree/dsl/import_dsl.rb +106 -0
- data/lib/ree/dsl/link_import_builder.rb +66 -0
- data/lib/ree/dsl/object_dsl.rb +319 -0
- data/lib/ree/dsl/object_hooks.rb +6 -0
- data/lib/ree/dsl/package_require.rb +44 -0
- data/lib/ree/error.rb +11 -0
- data/lib/ree/facades/packages_facade.rb +197 -0
- data/lib/ree/fn_dsl.rb +24 -0
- data/lib/ree/gen/init.rb +64 -0
- data/lib/ree/gen/package.rb +56 -0
- data/lib/ree/gen.rb +8 -0
- data/lib/ree/handlers/template_handler.rb +118 -0
- data/lib/ree/link_dsl.rb +175 -0
- data/lib/ree/object_compiler.rb +149 -0
- data/lib/ree/package_dsl.rb +34 -0
- data/lib/ree/rspec_link_dsl.rb +19 -0
- data/lib/ree/spec_runner/command_generator.rb +49 -0
- data/lib/ree/spec_runner/command_params.rb +9 -0
- data/lib/ree/spec_runner/runner.rb +200 -0
- data/lib/ree/spec_runner/spec_filename_matcher.rb +27 -0
- data/lib/ree/spec_runner/view.rb +30 -0
- data/lib/ree/spec_runner.rb +11 -0
- data/lib/ree/templates/init/.gitignore +1 -0
- data/lib/ree/templates/init/.irbrc +13 -0
- data/lib/ree/templates/init/.rspec +3 -0
- data/lib/ree/templates/init/.ruby-version +1 -0
- data/lib/ree/templates/init/Gemfile +7 -0
- data/lib/ree/templates/init/Packages.schema.json +1 -0
- data/lib/ree/templates/init/bin/console +5 -0
- data/lib/ree/templates/init/readme.md +2 -0
- data/lib/ree/templates/init/ree.setup.rb +21 -0
- data/lib/ree/templates/init/spec.init.rb +7 -0
- data/lib/ree/templates/package/.gitignore +0 -0
- data/lib/ree/templates/package/.rspec +2 -0
- data/lib/ree/templates/package/<%=package_subdir_name%>/<%=package_name%>/.gitkeep +0 -0
- data/lib/ree/templates/package/<%=package_subdir_name%>/<%=package_name%>.rb +15 -0
- data/lib/ree/templates/package/Package.schema.json +0 -0
- data/lib/ree/templates/package/bin/console +5 -0
- data/lib/ree/templates/package/spec/package_schema_spec.rb +14 -0
- data/lib/ree/templates/package/spec/spec_helper.rb +3 -0
- data/lib/ree/templates/template_detector.rb +35 -0
- data/lib/ree/templates/template_renderer.rb +55 -0
- data/lib/ree/utils/render_utils.rb +20 -0
- data/lib/ree/utils/string_utils.rb +29 -0
- data/lib/ree/version.rb +5 -0
- data/lib/ree.rb +279 -0
- data/sig/ree.rbs +4 -0
- metadata +199 -0
@@ -0,0 +1,149 @@
|
|
1
|
+
# frozen_string_literal = true
|
2
|
+
|
3
|
+
class Ree::ObjectCompiler
|
4
|
+
def initialize(packages_facade)
|
5
|
+
@packages_facade = packages_facade
|
6
|
+
@link_validator = Ree::LinkValidator.new(packages_facade)
|
7
|
+
end
|
8
|
+
|
9
|
+
# @param [Symbol] package_name
|
10
|
+
# @param [Symbol] object_name
|
11
|
+
# @return [Ree::Object]
|
12
|
+
def call(package_name, object_name)
|
13
|
+
@packages_facade.get_loaded_package(package_name)
|
14
|
+
object = @packages_facade.load_package_object(package_name, object_name)
|
15
|
+
|
16
|
+
object.set_as_compiled(true)
|
17
|
+
Ree.logger.debug("compile_object(:#{package_name}, :#{object_name}), object_id=#{object.object_id}")
|
18
|
+
|
19
|
+
klass = object.klass
|
20
|
+
links = object.links
|
21
|
+
eval_list = []
|
22
|
+
|
23
|
+
eval_list.push("\n# #{object.klass}")
|
24
|
+
indent = ""
|
25
|
+
|
26
|
+
links.each do |_|
|
27
|
+
eval_list.push(indent + "private attr_reader :#{_.as}")
|
28
|
+
end
|
29
|
+
|
30
|
+
eval_list.push("\n")
|
31
|
+
|
32
|
+
if object.singleton
|
33
|
+
eval_list.push(indent + "if !const_defined?(:SEMAPHORE)")
|
34
|
+
eval_list.push(indent + " SEMAPHORE = Mutex.new")
|
35
|
+
eval_list.push(indent + " private_constant :SEMAPHORE")
|
36
|
+
eval_list.push(indent + "end")
|
37
|
+
eval_list.push("\n")
|
38
|
+
end
|
39
|
+
|
40
|
+
if object.factory || object.singleton
|
41
|
+
eval_list.push(indent + "def self.new(**kwargs)")
|
42
|
+
|
43
|
+
if object.singleton
|
44
|
+
eval_list.push(indent + " SEMAPHORE.synchronize do")
|
45
|
+
eval_list.push(indent + " obj_links = #{links.map(&:as).inspect}")
|
46
|
+
eval_list.push(indent + " if (obj_links & kwargs.keys).size == 0")
|
47
|
+
eval_list.push(indent + " @__instance ||= begin")
|
48
|
+
|
49
|
+
if object.factory
|
50
|
+
eval_list.push(indent + " super(**kwargs).#{object.factory}")
|
51
|
+
else
|
52
|
+
eval_list.push(indent + " super(**kwargs)")
|
53
|
+
end
|
54
|
+
|
55
|
+
eval_list.push(indent + " end")
|
56
|
+
eval_list.push(indent + " else")
|
57
|
+
|
58
|
+
if object.factory
|
59
|
+
eval_list.push(indent + " super(**kwargs).#{object.factory}")
|
60
|
+
else
|
61
|
+
eval_list.push(indent + " super(**kwargs)")
|
62
|
+
end
|
63
|
+
|
64
|
+
eval_list.push(indent + " end")
|
65
|
+
eval_list.push(indent + " end")
|
66
|
+
else
|
67
|
+
eval_list.push(indent + " super(**kwargs).#{object.factory}")
|
68
|
+
end
|
69
|
+
|
70
|
+
eval_list.push(indent + "end")
|
71
|
+
end
|
72
|
+
|
73
|
+
eval_list.push("\n")
|
74
|
+
eval_list.push(indent + "def initialize(**kwargs)")
|
75
|
+
|
76
|
+
indent = inc_indent(indent)
|
77
|
+
|
78
|
+
links.each do |_|
|
79
|
+
@link_validator.call(object, _)
|
80
|
+
pckg = @packages_facade.get_loaded_package(_.package_name)
|
81
|
+
obj = pckg.get_object(_.object_name)
|
82
|
+
|
83
|
+
@packages_facade.load_package_object(pckg.name, obj.name)
|
84
|
+
|
85
|
+
eval_list.push(indent + "@#{_.as} = kwargs[:#{_.as}] || #{obj.klass}.new(**kwargs)")
|
86
|
+
end
|
87
|
+
|
88
|
+
if object.after_init?
|
89
|
+
eval_list.push(indent + "#{object.after_init}")
|
90
|
+
end
|
91
|
+
|
92
|
+
if object.compiled_frozen
|
93
|
+
eval_list.push(indent + 'freeze')
|
94
|
+
end
|
95
|
+
|
96
|
+
indent = dec_indent(indent)
|
97
|
+
|
98
|
+
eval_list.push(indent + 'end')
|
99
|
+
|
100
|
+
links.each do |_|
|
101
|
+
pckg = @packages_facade.get_loaded_package(_.package_name)
|
102
|
+
obj = pckg.get_object(_.object_name)
|
103
|
+
|
104
|
+
if obj.fn?
|
105
|
+
eval_list.push(indent + "\nprivate def #{_.as}(*args, **kwargs, &block)")
|
106
|
+
indent = inc_indent(indent)
|
107
|
+
eval_list.push(indent + "@#{_.as}.call(*args, **kwargs, &block)")
|
108
|
+
indent = dec_indent(indent)
|
109
|
+
eval_list.push(indent + "end")
|
110
|
+
else
|
111
|
+
eval_list.push(indent + "\nprivate def #{_.as}")
|
112
|
+
indent = inc_indent(indent)
|
113
|
+
eval_list.push(indent + "@#{_.as}")
|
114
|
+
indent = dec_indent(indent)
|
115
|
+
eval_list.push(indent + "end")
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
indent = dec_indent(indent)
|
120
|
+
|
121
|
+
str = eval_list.join("\n")
|
122
|
+
|
123
|
+
klass.class_eval <<-ruby_eval, __FILE__, __LINE__ + 1
|
124
|
+
#{str}
|
125
|
+
ruby_eval
|
126
|
+
|
127
|
+
# compile all linked objects
|
128
|
+
links.each do |link|
|
129
|
+
pckg = @packages_facade.get_loaded_package(link.package_name)
|
130
|
+
obj = pckg.get_object(link.object_name)
|
131
|
+
|
132
|
+
if !obj.compiled?
|
133
|
+
self.call(obj.package_name, obj.name)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
object
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
def inc_indent(indent)
|
143
|
+
indent += " "
|
144
|
+
end
|
145
|
+
|
146
|
+
def dec_indent(indent)
|
147
|
+
indent.slice(0, indent.size - 2)
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal = true
|
2
|
+
|
3
|
+
module Ree::PackageDSL
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.extended(base)
|
9
|
+
base.extend(ClassMethods)
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def package(&proc)
|
14
|
+
dsl = Ree::BuildPackageDsl.new(
|
15
|
+
Ree.container.packages_facade, self
|
16
|
+
)
|
17
|
+
|
18
|
+
dsl.instance_exec(&proc) if block_given?
|
19
|
+
|
20
|
+
return if dsl.package.preloaded?
|
21
|
+
dsl.package.set_preloaded(true)
|
22
|
+
|
23
|
+
dsl.package.preload.each do |env, list|
|
24
|
+
next if !Ree.preload_for?(env)
|
25
|
+
|
26
|
+
list.each do |object_name|
|
27
|
+
Ree.container.compile_object(
|
28
|
+
"#{dsl.package.name}/#{object_name}",
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Ree::RSpecLinkDSL
|
2
|
+
def link(obj_name, as: nil, from:)
|
3
|
+
obj = Ree.container.compile(from, obj_name)
|
4
|
+
|
5
|
+
if obj.nil?
|
6
|
+
raise Ree::Error.new("object :#{obj_name} was not found for package :#{from}")
|
7
|
+
end
|
8
|
+
|
9
|
+
as ||= obj_name
|
10
|
+
|
11
|
+
define_method as do |*args, **kwargs, &proc|
|
12
|
+
if obj.object?
|
13
|
+
obj.klass.new
|
14
|
+
else
|
15
|
+
obj.klass.new.call(*args, **kwargs, &proc)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal = true
|
2
|
+
|
3
|
+
class Ree::SpecRunner::CommandGenerator
|
4
|
+
attr_accessor :package_name, :package_path, :spec_matcher, :spec_string_number
|
5
|
+
|
6
|
+
def initialize(package_name:, package_path:, spec_matcher:, spec_string_number:, show_output: true)
|
7
|
+
@package_name = package_name
|
8
|
+
@package_path = File.expand_path(package_path)
|
9
|
+
@spec_matcher = spec_matcher
|
10
|
+
@spec_string_number = spec_string_number
|
11
|
+
@output = show_output ? '$stdout' : 'File::NULL'
|
12
|
+
end
|
13
|
+
|
14
|
+
def spec_count
|
15
|
+
Dir[File.join(package_path, 'spec/**/*_spec.rb')].size
|
16
|
+
end
|
17
|
+
|
18
|
+
def command
|
19
|
+
package_spec_path = File.join(package_path, 'spec')
|
20
|
+
package_spec_helper = File.join(package_path, 'spec', 'spec_helper.rb')
|
21
|
+
matcher = ""
|
22
|
+
|
23
|
+
if spec_matcher
|
24
|
+
matched_file = File.expand_path(spec_matcher, package_path)
|
25
|
+
matcher = File.exist?(matched_file) ? matcher_with_number(matched_file, spec_string_number) : matcher_with_number(spec_matcher, spec_string_number)
|
26
|
+
end
|
27
|
+
|
28
|
+
"print_message(
|
29
|
+
'**** Package: #{package_name} *****') \\
|
30
|
+
&& system('cd #{Ree.root_dir} \\
|
31
|
+
&& bundle exec rspec --color --tty #{matcher} --default-path=#{package_spec_path} --require=#{package_spec_helper}', \\
|
32
|
+
out: #{@output.to_s}, err: :out)"
|
33
|
+
end
|
34
|
+
|
35
|
+
def generate
|
36
|
+
Ree::SpecRunner::CommandParams.new.tap do |cp|
|
37
|
+
cp.package_name = package_name
|
38
|
+
cp.package_path = package_path
|
39
|
+
cp.command = command
|
40
|
+
cp.spec_count = spec_count
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def matcher_with_number(matcher_string, string_number)
|
47
|
+
string_number == 0 ? matcher_string : [matcher_string, string_number].join(':')
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
# frozen_string_literal = true
|
2
|
+
|
3
|
+
class Ree::SpecRunner::Runner
|
4
|
+
attr_accessor :no_specs_packages
|
5
|
+
attr_accessor :prepared_command_params
|
6
|
+
|
7
|
+
def initialize(path: nil, package: nil, spec_matcher: nil, show_missing_packages: true,
|
8
|
+
stdout: $stdout, show_output: true )
|
9
|
+
@package_name = package
|
10
|
+
@no_specs_packages = []
|
11
|
+
@spec_matcher = spec_matcher.to_s.split(':')[0]
|
12
|
+
@spec_string_number = spec_matcher.to_s.split(':')[1].to_i
|
13
|
+
@path = path
|
14
|
+
@stdout = stdout
|
15
|
+
@show_output = show_output
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
if @spec_matcher
|
20
|
+
find_matched_files(@package_name)
|
21
|
+
end
|
22
|
+
|
23
|
+
prepare!
|
24
|
+
check_input_params!
|
25
|
+
display_missing_specs if @show_missing_packages
|
26
|
+
print_message view.specs_header_message if @show_missing_packages
|
27
|
+
|
28
|
+
execute_command
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def prepare!
|
34
|
+
prepared_command_params = []
|
35
|
+
no_specs_packages = []
|
36
|
+
@command_params_list = []
|
37
|
+
prepare_command_params
|
38
|
+
prepare_no_specs_packages
|
39
|
+
prepare_command
|
40
|
+
end
|
41
|
+
|
42
|
+
def is_package_included?(package_name)
|
43
|
+
!prepared_command_params.select do |x|
|
44
|
+
x.package_name == package_name
|
45
|
+
end.empty?
|
46
|
+
end
|
47
|
+
|
48
|
+
def prepare_command_params
|
49
|
+
@prepared_command_params ||= begin
|
50
|
+
[
|
51
|
+
Ree::SpecRunner::CommandGenerator.new(
|
52
|
+
package_name: selected_package.name,
|
53
|
+
package_path: File.join(@path, selected_package.dir),
|
54
|
+
spec_matcher: @spec_matcher,
|
55
|
+
spec_string_number: @spec_string_number,
|
56
|
+
show_output: @show_output
|
57
|
+
).generate
|
58
|
+
]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def prepare_command
|
63
|
+
@command_params_list += prepare_single_package_command(@package_name)
|
64
|
+
end
|
65
|
+
|
66
|
+
def prepare_no_specs_packages
|
67
|
+
prepared_command_params
|
68
|
+
.select { |cp| cp.spec_count == 0 }
|
69
|
+
.map { |cp| no_specs_packages << cp.package_name }
|
70
|
+
end
|
71
|
+
|
72
|
+
def prepare_single_package_command(package_name)
|
73
|
+
selected = prepared_command_params.detect do |cmd_params|
|
74
|
+
cmd_params.package_name == package_name
|
75
|
+
end
|
76
|
+
|
77
|
+
prepare_commands_for_packages([selected])
|
78
|
+
end
|
79
|
+
|
80
|
+
def prepare_commands_for_packages(packages_command_params)
|
81
|
+
running_packages = packages_command_params
|
82
|
+
.select { |cmd_params| cmd_params.spec_count > 0 }
|
83
|
+
.sort_by { |cmd_params| cmd_params.package_name }
|
84
|
+
|
85
|
+
running_packages
|
86
|
+
end
|
87
|
+
|
88
|
+
def execute_command
|
89
|
+
@command_params_list.each do |command_param|
|
90
|
+
eval(command_param.command);
|
91
|
+
|
92
|
+
command_param.exitstatus = $?.exitstatus
|
93
|
+
end
|
94
|
+
|
95
|
+
failed = @command_params_list.select {|cmd_param| !cmd_param.success?}
|
96
|
+
|
97
|
+
if failed.any?
|
98
|
+
total_count = @command_params_list.count
|
99
|
+
failed_count = failed.count
|
100
|
+
|
101
|
+
print_message("#{failed_count} of #{total_count} packages failed:")
|
102
|
+
print_message(failed.map(&:package_name))
|
103
|
+
print_message("\n")
|
104
|
+
|
105
|
+
exit(1)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def check_input_params!
|
110
|
+
if @package_name
|
111
|
+
unless is_package_included?(@package_name)
|
112
|
+
exit_with_message(
|
113
|
+
view.package_not_found_message(@package_name, prepared_command_params)
|
114
|
+
)
|
115
|
+
end
|
116
|
+
|
117
|
+
if no_specs_packages.include?(@package_name)
|
118
|
+
print_message(
|
119
|
+
view.no_specs_for_package(@package_name)
|
120
|
+
)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def display_missing_specs
|
126
|
+
if !no_specs_packages.empty?
|
127
|
+
print_message view.missing_specs_message(no_specs_packages)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def find_matched_files(package_name)
|
132
|
+
@spec_file_matches = Ree::SpecRunner::SpecFilenameMatcher.find_matches(
|
133
|
+
package_path: File.join(@path, selected_package.dir),
|
134
|
+
spec_matcher: @spec_matcher
|
135
|
+
)
|
136
|
+
|
137
|
+
case @spec_file_matches.size
|
138
|
+
when 0
|
139
|
+
raise Ree::Error.new("No spec were found for #{@spec_matcher}")
|
140
|
+
when 1
|
141
|
+
format_string_number = @spec_string_number == 0 ? "" : ":#{@spec_string_number}"
|
142
|
+
@spec_matcher = @spec_file_matches.first
|
143
|
+
puts "Following spec matches your input: #{@spec_matcher + format_string_number}"
|
144
|
+
else
|
145
|
+
format_spec_files = @spec_file_matches.map.with_index { |file, idx| "#{idx + 1}. #{file}" }.join("\n")
|
146
|
+
|
147
|
+
puts "Following specs match your input:"
|
148
|
+
puts format_spec_files
|
149
|
+
print "Enter space-separated file numbers, ex: '1 2': "
|
150
|
+
selected_files_numbers = $stdin.gets.chomp
|
151
|
+
.split(' ')
|
152
|
+
.map {|x| Integer(x) rescue nil }
|
153
|
+
.compact
|
154
|
+
.map { |n| n - 1 }
|
155
|
+
.reject { |n| n >= @spec_file_matches.size }
|
156
|
+
|
157
|
+
|
158
|
+
@spec_file_matches
|
159
|
+
.select
|
160
|
+
.with_index { |_file, idx| selected_files_numbers.include?(idx) }
|
161
|
+
.each do |file|
|
162
|
+
Ree::SpecRunner::Runner.new(
|
163
|
+
path: @path,
|
164
|
+
package: package_name,
|
165
|
+
spec_matcher: file,
|
166
|
+
show_output: @show_output,
|
167
|
+
stdout: @stdout
|
168
|
+
).run
|
169
|
+
end
|
170
|
+
|
171
|
+
exit(0)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def container
|
176
|
+
@container = Ree.container
|
177
|
+
end
|
178
|
+
|
179
|
+
def selected_package
|
180
|
+
@selected_package ||= packages.find { |p| p.name == @package_name }
|
181
|
+
end
|
182
|
+
|
183
|
+
def packages
|
184
|
+
@packages ||= container.packages_facade.load_packages_schema.packages
|
185
|
+
end
|
186
|
+
|
187
|
+
def view
|
188
|
+
@view ||= Ree::SpecRunner::View.new
|
189
|
+
end
|
190
|
+
|
191
|
+
def print_message(msg)
|
192
|
+
@stdout.puts msg
|
193
|
+
true
|
194
|
+
end
|
195
|
+
|
196
|
+
def exit_with_message(msg)
|
197
|
+
print_message(msg)
|
198
|
+
exit 1
|
199
|
+
end
|
200
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal = true
|
2
|
+
|
3
|
+
class Ree::SpecRunner::SpecFilenameMatcher
|
4
|
+
class << self
|
5
|
+
def find_matches(package_path:, spec_matcher:)
|
6
|
+
Ree::SpecRunner::SpecFilenameMatcher.new(package_path, spec_matcher).find_matches
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(package_path, spec_matcher)
|
11
|
+
@package_path = File.expand_path(package_path)
|
12
|
+
@spec_matcher = spec_matcher
|
13
|
+
end
|
14
|
+
|
15
|
+
def find_matches
|
16
|
+
expected_filename = File.join(@package_path, @spec_matcher)
|
17
|
+
|
18
|
+
if File.exist?(expected_filename)
|
19
|
+
return Pathname.new(expected_filename).relative_path_from(Pathname.new(@package_path)).to_s.split
|
20
|
+
end
|
21
|
+
|
22
|
+
Dir.glob(File.join(@package_path, '**/*_spec.rb'))
|
23
|
+
.select { |fn| File.file?(fn) }
|
24
|
+
.map {|file| Pathname.new(file).relative_path_from(Pathname.new(@package_path)).to_s }
|
25
|
+
.grep(/#{@spec_matcher.split('').join('.*')}/)
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal = true
|
2
|
+
|
3
|
+
class Ree::SpecRunner::View
|
4
|
+
def packages_menu(prepared_command_params)
|
5
|
+
prepared_command_params
|
6
|
+
.sort_by(&:package_path)
|
7
|
+
.map { |x| " - #{x.package_name} (#{x.spec_count} spec files)" }
|
8
|
+
.join("\n")
|
9
|
+
end
|
10
|
+
|
11
|
+
def package_not_found_message(package_name, prepared_command_params)
|
12
|
+
"Package #{package_name} not found! \nPossible packages:\n\n#{packages_menu(prepared_command_params)}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def missing_specs_message(skipped_packages)
|
16
|
+
"NO SPECS FOUND FOR PACKAGES: \n#{skipped_packages.map { |x| " - #{x}" }.join("\n")}\n\n"
|
17
|
+
end
|
18
|
+
|
19
|
+
def skipping_specs_message(skipped_packages)
|
20
|
+
"FOLLOWING PACKAGES WERE SKIPPED BY .runignore FILE: \n#{skipped_packages.map { |x| " - #{x}" }.join("\n")}\n\n"
|
21
|
+
end
|
22
|
+
|
23
|
+
def specs_header_message
|
24
|
+
"**** SPECS *****"
|
25
|
+
end
|
26
|
+
|
27
|
+
def no_specs_for_package(package_name)
|
28
|
+
"Package #{package_name} has no specs to execute!"
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal = true
|
2
|
+
|
3
|
+
module Ree
|
4
|
+
module SpecRunner
|
5
|
+
autoload :SpecFilenameMatcher, 'ree/spec_runner/spec_filename_matcher'
|
6
|
+
autoload :CommandGenerator, 'ree/spec_runner/command_generator'
|
7
|
+
autoload :CommandParams, 'ree/spec_runner/command_params'
|
8
|
+
autoload :Runner, 'ree/spec_runner/runner'
|
9
|
+
autoload :View, 'ree/spec_runner/view'
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
.irb_history
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class Object
|
2
|
+
def local_methods
|
3
|
+
(instance_methods - Object.instance_methods).sort
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
def link(obj_name, from:)
|
8
|
+
obj = Ree.container.packages_facade.get_object(from, obj_name)
|
9
|
+
|
10
|
+
define_method obj_name do |*args, **kwargs, &proc|
|
11
|
+
obj.klass.new.call(*args, **kwargs, &proc)
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= RUBY_VERSION %>
|
@@ -0,0 +1 @@
|
|
1
|
+
{}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
Ree.add_error_types(
|
3
|
+
:invalid_param,
|
4
|
+
:not_found,
|
5
|
+
:validation
|
6
|
+
)
|
7
|
+
|
8
|
+
# Switch Ree.logger to debug level
|
9
|
+
# Ree.set_logger_debug
|
10
|
+
|
11
|
+
if ENV['RUBY_ENV'] == 'test'
|
12
|
+
Ree.enable_contracts
|
13
|
+
end
|
14
|
+
|
15
|
+
if ENV['RUBY_ENV'] == 'production'
|
16
|
+
# Define preload context for registered objects
|
17
|
+
Ree.preload_for(:production)
|
18
|
+
|
19
|
+
# Use performance mode to load packages and registered objects based on schema files
|
20
|
+
Ree.set_performance_mode
|
21
|
+
end
|
File without changes
|
File without changes
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module <%= Ree::StringUtils.camelize(package_name) %>
|
2
|
+
include Ree::PackageDSL
|
3
|
+
|
4
|
+
package do
|
5
|
+
# Example of usage:
|
6
|
+
# tags ['wip']
|
7
|
+
# depends_on :package_name
|
8
|
+
# env_var 'ENV_VAR_NAME'
|
9
|
+
# preload(
|
10
|
+
# production: [
|
11
|
+
# :bean_or_fn
|
12
|
+
# ]
|
13
|
+
# )
|
14
|
+
end
|
15
|
+
end
|
File without changes
|
@@ -0,0 +1,14 @@
|
|
1
|
+
RSpec.describe "<%= Ree::StringUtils.camelize(package_name) %>" do
|
2
|
+
it "generates package schema" do
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
packages_schema_path = Ree.locate_packages_schema(__dir__)
|
6
|
+
packages_schema_dir = Pathname.new(packages_schema_path).dirname.to_s
|
7
|
+
|
8
|
+
FileUtils.cd packages_schema_dir do
|
9
|
+
expect(
|
10
|
+
system("bundle exec ree gen.package_json <%= package_name %> --silence")
|
11
|
+
).to eq(true)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|