mutant 0.9.10 → 0.10.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.
Files changed (254) hide show
  1. checksums.yaml +4 -4
  2. data/bin/mutant +16 -11
  3. data/lib/mutant.rb +8 -4
  4. data/lib/mutant/bootstrap.rb +14 -1
  5. data/lib/mutant/cli.rb +9 -162
  6. data/lib/mutant/cli/command.rb +196 -0
  7. data/lib/mutant/cli/command/root.rb +13 -0
  8. data/lib/mutant/cli/command/run.rb +151 -0
  9. data/lib/mutant/cli/command/subscription.rb +54 -0
  10. data/lib/mutant/expression.rb +0 -1
  11. data/lib/mutant/isolation.rb +1 -1
  12. data/lib/mutant/isolation/fork.rb +2 -2
  13. data/lib/mutant/isolation/none.rb +1 -1
  14. data/lib/mutant/license.rb +9 -35
  15. data/lib/mutant/license/subscription.rb +31 -9
  16. data/lib/mutant/license/subscription/commercial.rb +2 -4
  17. data/lib/mutant/license/subscription/opensource.rb +7 -7
  18. data/lib/mutant/matcher/config.rb +2 -0
  19. data/lib/mutant/meta/example.rb +16 -4
  20. data/lib/mutant/meta/example/dsl.rb +33 -16
  21. data/lib/mutant/meta/example/verification.rb +70 -28
  22. data/lib/mutant/minitest/coverage.rb +53 -0
  23. data/lib/mutant/mutator/node.rb +2 -2
  24. data/lib/mutant/mutator/node/block_pass.rb +29 -0
  25. data/lib/mutant/mutator/node/{dstr.rb → dynamic_literal.rb} +7 -5
  26. data/lib/mutant/mutator/node/index.rb +4 -4
  27. data/lib/mutant/mutator/node/literal/range.rb +5 -2
  28. data/lib/mutant/mutator/node/named_value/variable_assignment.rb +1 -1
  29. data/lib/mutant/mutator/node/noop.rb +1 -1
  30. data/lib/mutant/mutator/node/op_asgn.rb +15 -1
  31. data/lib/mutant/mutator/node/send.rb +25 -1
  32. data/lib/mutant/mutator/node/send/attribute_assignment.rb +1 -0
  33. data/lib/mutant/reporter/cli/printer/isolation_result.rb +9 -3
  34. data/lib/mutant/subject/method/instance.rb +1 -1
  35. data/lib/mutant/version.rb +1 -1
  36. metadata +18 -336
  37. data/.github/workflows/ci.yml +0 -121
  38. data/.gitignore +0 -38
  39. data/.rspec +0 -5
  40. data/.rubocop.yml +0 -210
  41. data/Changelog.md +0 -87
  42. data/Gemfile +0 -7
  43. data/Gemfile.lock +0 -107
  44. data/Gemfile.shared +0 -10
  45. data/README.md +0 -199
  46. data/Rakefile +0 -5
  47. data/config/devtools.yml +0 -2
  48. data/config/reek.yml +0 -139
  49. data/config/yardstick.yml +0 -2
  50. data/docs/commercial-support.md +0 -14
  51. data/docs/concurrency.md +0 -39
  52. data/docs/incremental.md +0 -76
  53. data/docs/known-problems.md +0 -30
  54. data/docs/limitations.md +0 -50
  55. data/docs/mutant-minitest.md +0 -149
  56. data/docs/mutant-rspec.md +0 -130
  57. data/docs/nomenclature.md +0 -82
  58. data/docs/reading-reports.md +0 -74
  59. data/lib/mutant/mutator/node/dsym.rb +0 -22
  60. data/meta/and.rb +0 -13
  61. data/meta/and_asgn.rb +0 -14
  62. data/meta/array.rb +0 -27
  63. data/meta/begin.rb +0 -20
  64. data/meta/block.rb +0 -199
  65. data/meta/block_pass.rb +0 -8
  66. data/meta/blockarg.rb +0 -10
  67. data/meta/break.rb +0 -9
  68. data/meta/case.rb +0 -217
  69. data/meta/casgn.rb +0 -25
  70. data/meta/cbase.rb +0 -8
  71. data/meta/class.rb +0 -12
  72. data/meta/const.rb +0 -17
  73. data/meta/csend.rb +0 -10
  74. data/meta/cvar.rb +0 -7
  75. data/meta/cvasgn.rb +0 -9
  76. data/meta/date.rb +0 -59
  77. data/meta/def.rb +0 -196
  78. data/meta/defined.rb +0 -9
  79. data/meta/dstr.rb +0 -13
  80. data/meta/dsym.rb +0 -14
  81. data/meta/ensure.rb +0 -8
  82. data/meta/false.rb +0 -7
  83. data/meta/file.rb +0 -5
  84. data/meta/float.rb +0 -37
  85. data/meta/gvar.rb +0 -7
  86. data/meta/gvasgn.rb +0 -9
  87. data/meta/hash.rb +0 -20
  88. data/meta/if.rb +0 -72
  89. data/meta/index.rb +0 -133
  90. data/meta/indexasgn.rb +0 -31
  91. data/meta/int.rb +0 -18
  92. data/meta/ivar.rb +0 -8
  93. data/meta/ivasgn.rb +0 -22
  94. data/meta/kwarg.rb +0 -10
  95. data/meta/kwbegin.rb +0 -8
  96. data/meta/kwoptarg.rb +0 -13
  97. data/meta/lambda.rb +0 -23
  98. data/meta/line.rb +0 -5
  99. data/meta/lvar.rb +0 -16
  100. data/meta/lvasgn.rb +0 -24
  101. data/meta/masgn.rb +0 -7
  102. data/meta/match_current_line.rb +0 -14
  103. data/meta/next.rb +0 -10
  104. data/meta/nil.rb +0 -5
  105. data/meta/nthref.rb +0 -14
  106. data/meta/op_assgn.rb +0 -17
  107. data/meta/or.rb +0 -13
  108. data/meta/or_asgn.rb +0 -50
  109. data/meta/range.rb +0 -65
  110. data/meta/redo.rb +0 -5
  111. data/meta/regexp.rb +0 -80
  112. data/meta/regopt.rb +0 -10
  113. data/meta/rescue.rb +0 -84
  114. data/meta/return.rb +0 -16
  115. data/meta/sclass.rb +0 -12
  116. data/meta/self.rb +0 -7
  117. data/meta/send.rb +0 -600
  118. data/meta/str.rb +0 -7
  119. data/meta/super.rb +0 -27
  120. data/meta/sym.rb +0 -8
  121. data/meta/true.rb +0 -7
  122. data/meta/until.rb +0 -16
  123. data/meta/while.rb +0 -24
  124. data/meta/yield.rb +0 -9
  125. data/mutant-minitest.gemspec +0 -22
  126. data/mutant-rspec.gemspec +0 -22
  127. data/mutant.gemspec +0 -44
  128. data/mutant.sh +0 -12
  129. data/mutant.yml +0 -6
  130. data/spec/integration/mutant/corpus_spec.rb +0 -15
  131. data/spec/integration/mutant/isolation/fork_spec.rb +0 -28
  132. data/spec/integration/mutant/minitest_spec.rb +0 -11
  133. data/spec/integration/mutant/null_spec.rb +0 -16
  134. data/spec/integration/mutant/rspec_spec.rb +0 -15
  135. data/spec/integration/mutant/test_mutator_handles_types_spec.rb +0 -9
  136. data/spec/integrations.yml +0 -63
  137. data/spec/shared/framework_integration_behavior.rb +0 -70
  138. data/spec/shared/method_matcher_behavior.rb +0 -47
  139. data/spec/spec_helper.rb +0 -90
  140. data/spec/support/corpus.rb +0 -318
  141. data/spec/support/file_system.rb +0 -62
  142. data/spec/support/ice_nine_config.rb +0 -10
  143. data/spec/support/ruby_vm.rb +0 -84
  144. data/spec/support/shared_context.rb +0 -169
  145. data/spec/support/xspec.rb +0 -183
  146. data/spec/unit/mutant/ast/find_metaclass_containing_spec.rb +0 -64
  147. data/spec/unit/mutant/ast/meta/optarg_spec.rb +0 -24
  148. data/spec/unit/mutant/ast/meta/send/proc_predicate_spec.rb +0 -30
  149. data/spec/unit/mutant/ast/meta/send/receiver_possible_top_level_const_predicate_spec.rb +0 -39
  150. data/spec/unit/mutant/ast/meta/send_spec.rb +0 -42
  151. data/spec/unit/mutant/ast/named_children_spec.rb +0 -89
  152. data/spec/unit/mutant/ast/sexp_spec.rb +0 -38
  153. data/spec/unit/mutant/ast_spec.rb +0 -57
  154. data/spec/unit/mutant/bootstrap_spec.rb +0 -216
  155. data/spec/unit/mutant/cli_spec.rb +0 -305
  156. data/spec/unit/mutant/clock_monotonic_spec.rb +0 -52
  157. data/spec/unit/mutant/config_spec.rb +0 -126
  158. data/spec/unit/mutant/context_spec.rb +0 -111
  159. data/spec/unit/mutant/env_spec.rb +0 -229
  160. data/spec/unit/mutant/expression/method_spec.rb +0 -62
  161. data/spec/unit/mutant/expression/methods_spec.rb +0 -66
  162. data/spec/unit/mutant/expression/namespace/exact_spec.rb +0 -28
  163. data/spec/unit/mutant/expression/namespace/recursive_spec.rb +0 -66
  164. data/spec/unit/mutant/expression/parser_spec.rb +0 -65
  165. data/spec/unit/mutant/expression_spec.rb +0 -45
  166. data/spec/unit/mutant/integration/rspec_spec.rb +0 -201
  167. data/spec/unit/mutant/integration_spec.rb +0 -150
  168. data/spec/unit/mutant/isolation/fork_spec.rb +0 -309
  169. data/spec/unit/mutant/isolation/none_spec.rb +0 -23
  170. data/spec/unit/mutant/isolation/result_spec.rb +0 -73
  171. data/spec/unit/mutant/license_spec.rb +0 -305
  172. data/spec/unit/mutant/loader_spec.rb +0 -79
  173. data/spec/unit/mutant/matcher/chain_spec.rb +0 -26
  174. data/spec/unit/mutant/matcher/compiler_spec.rb +0 -0
  175. data/spec/unit/mutant/matcher/config_spec.rb +0 -47
  176. data/spec/unit/mutant/matcher/filter_spec.rb +0 -22
  177. data/spec/unit/mutant/matcher/method/instance_spec.rb +0 -164
  178. data/spec/unit/mutant/matcher/method/metaclass_spec.rb +0 -108
  179. data/spec/unit/mutant/matcher/method/singleton_spec.rb +0 -90
  180. data/spec/unit/mutant/matcher/methods/instance_spec.rb +0 -54
  181. data/spec/unit/mutant/matcher/methods/metaclass_spec.rb +0 -62
  182. data/spec/unit/mutant/matcher/methods/singleton_spec.rb +0 -51
  183. data/spec/unit/mutant/matcher/namespace_spec.rb +0 -39
  184. data/spec/unit/mutant/matcher/null_spec.rb +0 -12
  185. data/spec/unit/mutant/matcher/scope_spec.rb +0 -45
  186. data/spec/unit/mutant/matcher/static_spec.rb +0 -13
  187. data/spec/unit/mutant/matcher_spec.rb +0 -102
  188. data/spec/unit/mutant/meta/example/dsl_spec.rb +0 -108
  189. data/spec/unit/mutant/meta/example/verification_spec.rb +0 -154
  190. data/spec/unit/mutant/meta/example_spec.rb +0 -34
  191. data/spec/unit/mutant/mutation_spec.rb +0 -140
  192. data/spec/unit/mutant/mutator/node_spec.rb +0 -47
  193. data/spec/unit/mutant/mutator_spec.rb +0 -21
  194. data/spec/unit/mutant/parallel/driver_spec.rb +0 -126
  195. data/spec/unit/mutant/parallel/source/array_spec.rb +0 -57
  196. data/spec/unit/mutant/parallel/worker_spec.rb +0 -206
  197. data/spec/unit/mutant/parallel_spec.rb +0 -115
  198. data/spec/unit/mutant/parser_spec.rb +0 -26
  199. data/spec/unit/mutant/range_spec.rb +0 -141
  200. data/spec/unit/mutant/registry_spec.rb +0 -74
  201. data/spec/unit/mutant/reporter/cli/printer/config_spec.rb +0 -17
  202. data/spec/unit/mutant/reporter/cli/printer/env_progress_spec.rb +0 -85
  203. data/spec/unit/mutant/reporter/cli/printer/env_result_spec.rb +0 -45
  204. data/spec/unit/mutant/reporter/cli/printer/isolation_result_spec.rb +0 -132
  205. data/spec/unit/mutant/reporter/cli/printer/mutation_progress_result_spec.rb +0 -25
  206. data/spec/unit/mutant/reporter/cli/printer/mutation_result_spec.rb +0 -153
  207. data/spec/unit/mutant/reporter/cli/printer/status_progressive_spec.rb +0 -45
  208. data/spec/unit/mutant/reporter/cli/printer/subject_progress_spec.rb +0 -36
  209. data/spec/unit/mutant/reporter/cli/printer/subject_result_spec.rb +0 -44
  210. data/spec/unit/mutant/reporter/cli/printer/test_result_spec.rb +0 -16
  211. data/spec/unit/mutant/reporter/cli/printer_spec.rb +0 -163
  212. data/spec/unit/mutant/reporter/cli_spec.rb +0 -137
  213. data/spec/unit/mutant/reporter/null_spec.rb +0 -14
  214. data/spec/unit/mutant/reporter/sequence_spec.rb +0 -31
  215. data/spec/unit/mutant/repository/diff/ranges_spec.rb +0 -180
  216. data/spec/unit/mutant/repository/diff_spec.rb +0 -122
  217. data/spec/unit/mutant/repository/subject_filter_spec.rb +0 -30
  218. data/spec/unit/mutant/require_highjack_spec.rb +0 -73
  219. data/spec/unit/mutant/result/class_methods_spec.rb +0 -51
  220. data/spec/unit/mutant/result/env_spec.rb +0 -161
  221. data/spec/unit/mutant/result/mutation_spec.rb +0 -70
  222. data/spec/unit/mutant/result/subject_spec.rb +0 -111
  223. data/spec/unit/mutant/result/test_spec.rb +0 -14
  224. data/spec/unit/mutant/result_spec.rb +0 -33
  225. data/spec/unit/mutant/runner/sink_spec.rb +0 -174
  226. data/spec/unit/mutant/runner_spec.rb +0 -121
  227. data/spec/unit/mutant/selector/expression_spec.rb +0 -62
  228. data/spec/unit/mutant/selector/null_spec.rb +0 -17
  229. data/spec/unit/mutant/subject/method/instance_spec.rb +0 -276
  230. data/spec/unit/mutant/subject/method/metaclass_spec.rb +0 -63
  231. data/spec/unit/mutant/subject/method/singleton_spec.rb +0 -61
  232. data/spec/unit/mutant/subject_spec.rb +0 -93
  233. data/spec/unit/mutant/transform/array_spec.rb +0 -92
  234. data/spec/unit/mutant/transform/bool_spec.rb +0 -63
  235. data/spec/unit/mutant/transform/error_spec.rb +0 -132
  236. data/spec/unit/mutant/transform/exception_spec.rb +0 -44
  237. data/spec/unit/mutant/transform/hash_spec.rb +0 -236
  238. data/spec/unit/mutant/transform/index_spec.rb +0 -92
  239. data/spec/unit/mutant/transform/named_spec.rb +0 -49
  240. data/spec/unit/mutant/transform/primitive_spec.rb +0 -56
  241. data/spec/unit/mutant/transform/sequence_spec.rb +0 -98
  242. data/spec/unit/mutant/util/one_spec.rb +0 -22
  243. data/spec/unit/mutant/warnings_spec.rb +0 -89
  244. data/spec/unit/mutant/world_spec.rb +0 -63
  245. data/spec/unit/mutant/zombifier_spec.rb +0 -122
  246. data/test_app/.rspec +0 -1
  247. data/test_app/Gemfile.minitest +0 -6
  248. data/test_app/Gemfile.rspec3.8 +0 -7
  249. data/test_app/lib/test_app.rb +0 -114
  250. data/test_app/lib/test_app/literal.rb +0 -35
  251. data/test_app/lib/test_app/metaclasses.rb +0 -108
  252. data/test_app/spec/spec_helper.rb +0 -9
  253. data/test_app/spec/unit/test_app/literal_spec.rb +0 -20
  254. data/test_app/test/unit/test_app/literal_test.rb +0 -16
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mutant
4
+ module CLI
5
+ class Command
6
+ class Root < self
7
+ SUBCOMMANDS = [Run, Subscription].freeze
8
+ SHORT_DESCRIPTION = 'mutation testing engine main command'
9
+ NAME = 'mutant'
10
+ end
11
+ end # Command
12
+ end # CLI
13
+ end # Mutant
@@ -0,0 +1,151 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mutant
4
+ module CLI
5
+ class Command
6
+ # rubocop:disable Metrics/ClassLength
7
+ class Run < self
8
+ NAME = 'run'
9
+ SHORT_DESCRIPTION = 'Run code analysis'
10
+
11
+ OPTIONS =
12
+ %i[
13
+ add_environment_options
14
+ add_runner_options
15
+ add_integration_options
16
+ add_matcher_options
17
+ ].freeze
18
+
19
+ SLEEP = 40
20
+
21
+ UNLICENSED = <<~MESSAGE.lines.freeze
22
+ Soft fail, continuing in #{SLEEP} seconds
23
+ Next major version will enforce the license
24
+ See https://github.com/mbj/mutant#licensing
25
+ MESSAGE
26
+
27
+ # Test if command needs to be executed in zombie environment
28
+ #
29
+ # @return [Bool]
30
+ def zombie?
31
+ config.zombie
32
+ end
33
+
34
+ private
35
+
36
+ def execute
37
+ soft_fail(License.apply(world))
38
+ .bind { Config.load_config_file(world, config) }
39
+ .bind { |cli_config| Bootstrap.apply(world, cli_config) }
40
+ .bind(&Runner.public_method(:apply))
41
+ .from_right { |error| world.stderr.puts(error); return false }
42
+ .success?
43
+ end
44
+
45
+ def soft_fail(result)
46
+ result.either(
47
+ lambda do |message|
48
+ stderr = world.stderr
49
+ stderr.puts(message)
50
+ UNLICENSED.each { |line| stderr.puts(unlicensed(line)) }
51
+ world.kernel.sleep(SLEEP)
52
+ Either::Right.new(nil)
53
+ end,
54
+ ->(_subscription) { Either::Right.new(nil) }
55
+ )
56
+ end
57
+
58
+ def unlicensed(message)
59
+ "[Mutant-License-Error]: #{message}"
60
+ end
61
+
62
+ def parse_remaining_arguments(arguments)
63
+ traverse(config.expression_parser.public_method(:apply), arguments)
64
+ .fmap do |match_expressions|
65
+ matcher(match_expressions: match_expressions)
66
+ self
67
+ end
68
+ end
69
+
70
+ def traverse(action, values)
71
+ Either::Right.new(
72
+ values.map do |value|
73
+ action.call(value).from_right do |error|
74
+ return Either::Left.new(error)
75
+ end
76
+ end
77
+ )
78
+ end
79
+
80
+ def set(**attributes)
81
+ @config = config.with(attributes)
82
+ end
83
+
84
+ def matcher(**attributes)
85
+ set(matcher: config.matcher.with(attributes))
86
+ end
87
+
88
+ def add(attribute, value)
89
+ set(attribute => config.public_send(attribute) + [value])
90
+ end
91
+
92
+ def add_matcher(attribute, value)
93
+ set(matcher: config.matcher.add(attribute, value))
94
+ end
95
+
96
+ def add_environment_options(parser)
97
+ parser.separator('Environment:')
98
+ parser.on('--zombie', 'Run mutant zombified') do
99
+ set(zombie: true)
100
+ end
101
+ parser.on('-I', '--include DIRECTORY', 'Add DIRECTORY to $LOAD_PATH') do |directory|
102
+ add(:includes, directory)
103
+ end
104
+ parser.on('-r', '--require NAME', 'Require file with NAME') do |name|
105
+ add(:requires, name)
106
+ end
107
+ end
108
+
109
+ def add_integration_options(parser)
110
+ parser.separator('Integration:')
111
+
112
+ parser.on('--use INTEGRATION', 'Use INTEGRATION to kill mutations') do |name|
113
+ set(integration: name)
114
+ end
115
+ end
116
+
117
+ # rubocop:disable Metrics/MethodLength
118
+ def add_matcher_options(parser)
119
+ parser.separator('Matcher:')
120
+
121
+ parser.on('--ignore-subject EXPRESSION', 'Ignore subjects that match EXPRESSION as prefix') do |pattern|
122
+ add_matcher(:ignore_expressions, config.expression_parser.apply(pattern).from_right)
123
+ end
124
+ parser.on('--start-subject EXPRESSION', 'Start mutation testing at a specific subject') do |pattern|
125
+ add_matcher(:start_expressions, config.expression_parser.apply(pattern).from_right)
126
+ end
127
+ parser.on('--since REVISION', 'Only select subjects touched since REVISION') do |revision|
128
+ add_matcher(
129
+ :subject_filters,
130
+ Repository::SubjectFilter.new(
131
+ Repository::Diff.new(to: revision, world: world)
132
+ )
133
+ )
134
+ end
135
+ end
136
+
137
+ def add_runner_options(parser)
138
+ parser.separator('Runner:')
139
+
140
+ parser.on('--fail-fast', 'Fail fast') do
141
+ set(fail_fast: true)
142
+ end
143
+ parser.on('-j', '--jobs NUMBER', 'Number of kill jobs. Defaults to number of processors.') do |number|
144
+ set(jobs: Integer(number))
145
+ end
146
+ end
147
+ end # Run
148
+ # rubocop:enable Metrics/ClassLength
149
+ end # Command
150
+ end # CLI
151
+ end # Mutant
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mutant
4
+ module CLI
5
+ class Command
6
+ class Subscription < self
7
+ NAME = 'subscription'
8
+ SHORT_DESCRIPTION = 'Subscription subcommands'
9
+
10
+ private
11
+
12
+ def license
13
+ License.apply(world)
14
+ end
15
+
16
+ class Test < self
17
+ NAME = 'test'
18
+ SUBCOMMANDS = [].freeze
19
+ SHORT_DESCRIPTION = 'Silently validates subscription, exits accordingly'
20
+
21
+ private
22
+
23
+ def execute
24
+ license.right?
25
+ end
26
+ end # Test
27
+
28
+ class Show < self
29
+ NAME = 'show'
30
+ SUBCOMMANDS = [].freeze
31
+ SHORT_DESCRIPTION = 'Show subscription status'
32
+
33
+ private
34
+
35
+ def execute
36
+ license.either(method(:unlicensed), method(:licensed))
37
+ end
38
+
39
+ def licensed(subscription)
40
+ world.stdout.puts(subscription.description)
41
+ true
42
+ end
43
+
44
+ def unlicensed(message)
45
+ world.stderr.puts(message)
46
+ false
47
+ end
48
+ end # Show
49
+
50
+ SUBCOMMANDS = [Show, Test].freeze
51
+ end # Subscription
52
+ end # Command
53
+ end # CLI
54
+ end # Mutant
@@ -59,6 +59,5 @@ module Mutant
59
59
  names = anima.attribute_names
60
60
  new(Hash[names.zip(names.map(&match.method(:[])))])
61
61
  end
62
-
63
62
  end # Expression
64
63
  end # Mutant
@@ -40,7 +40,7 @@ module Mutant
40
40
  instance_of?(Success)
41
41
  end
42
42
 
43
- # Succesful result producing value
43
+ # Successful result producing value
44
44
  class Success < self
45
45
  include Concord::Public.new(:value, :log)
46
46
 
@@ -10,12 +10,12 @@ module Mutant
10
10
 
11
11
  ATTRIBUTES = %i[block log_pipe result_pipe world].freeze
12
12
 
13
- # Unsucessful result as child exited nonzero
13
+ # Unsuccessful result as child exited nonzero
14
14
  class ChildError < Result
15
15
  include Concord::Public.new(:value, :log)
16
16
  end # ChildError
17
17
 
18
- # Unsucessful result as fork failed
18
+ # Unsuccessful result as fork failed
19
19
  class ForkError < Result
20
20
  include Equalizer.new
21
21
  end # ForkError
@@ -3,7 +3,7 @@
3
3
  module Mutant
4
4
  # Module providing isolation
5
5
  class Isolation
6
- # Absolutly no isolation
6
+ # Absolutely no isolation
7
7
  #
8
8
  # Only useful for debugging.
9
9
  class None < self
@@ -4,53 +4,27 @@ module Mutant
4
4
  module License
5
5
  NAME = 'mutant-license'
6
6
  VERSION = '~> 0.1.0'
7
- SLEEP = 40
8
-
9
- UNLICENSED =
10
- IceNine.deep_freeze(
11
- [
12
- "Soft fail, continuing in #{SLEEP} seconds",
13
- 'Next major version will enforce the license',
14
- 'See https://github.com/mbj/mutant#licensing'
15
- ]
16
- )
17
7
 
8
+ # Load license
9
+ #
10
+ # @param [World] world
11
+ #
12
+ # @return [Either<String,Subscription>]
13
+ #
14
+ # @api private
18
15
  def self.apply(world)
19
- soft_fail(world, license_result(world))
20
- end
21
-
22
- def self.license_result(world)
23
16
  load_mutant_license(world)
24
17
  .fmap { license_path(world) }
25
- .fmap { |path| Subscription.from_json(world.json.load(path)) }
26
- .bind { |sub| sub.apply(world) }
18
+ .bind { |path| Subscription.load(world, world.json.load(path)) }
27
19
  end
28
- private_class_method :license_result
29
-
30
- # ignore :reek:NestedIterators
31
- def self.soft_fail(world, result)
32
- result.lmap do |message|
33
- stderr = world.stderr
34
- stderr.puts(message)
35
- UNLICENSED.each { |line| stderr.puts(unlicensed(line)) }
36
- world.kernel.sleep(SLEEP)
37
- end
38
-
39
- Either::Right.new(true)
40
- end
41
- private_class_method :soft_fail
42
20
 
43
21
  def self.load_mutant_license(world)
44
22
  Either
45
23
  .wrap_error(LoadError) { world.gem_method.call(NAME, VERSION) }
46
24
  .lmap(&:message)
47
25
  .lmap(&method(:check_for_rubygems_mutant_license))
48
- .lmap(&method(:unlicensed))
49
- end
50
-
51
- def self.unlicensed(message)
52
- "[Mutant-License-Error]: #{message}"
53
26
  end
27
+ private_class_method :load_mutant_license
54
28
 
55
29
  def self.check_for_rubygems_mutant_license(message)
56
30
  if message.include?('already activated mutant-license-0.0.0')
@@ -3,8 +3,15 @@
3
3
  module Mutant
4
4
  module License
5
5
  class Subscription
6
+ include Concord.new(:licensed)
6
7
 
7
- MESSAGE_FORMAT = <<~'MESSAGE'
8
+ FORMAT = <<~'MESSAGE'
9
+ %<subscription_name>s subscription:
10
+ Licensed:
11
+ %<licensed>s
12
+ MESSAGE
13
+
14
+ FAILURE_FORMAT = <<~'MESSAGE'
8
15
  Can not validate %<subscription_name>s license.
9
16
  Licensed:
10
17
  %<expected>s
@@ -12,31 +19,46 @@ module Mutant
12
19
  %<actual>s
13
20
  MESSAGE
14
21
 
15
- def self.from_json(value)
22
+ # Load value into subscription
23
+ #
24
+ # @param [Object] value
25
+ #
26
+ # @return [Subscription]
27
+ def self.load(world, value)
16
28
  {
17
29
  'com' => Commercial,
18
30
  'oss' => Opensource
19
- }.fetch(value.fetch('type')).from_json(value.fetch('contents'))
31
+ }.fetch(value.fetch('type'))
32
+ .from_json(value.fetch('contents'))
33
+ .apply(world)
34
+ end
35
+
36
+ # Subscription self description
37
+ #
38
+ # @return [String]
39
+ def description
40
+ FORMAT % {
41
+ licensed: licensed.join("\n"),
42
+ subscription_name: subscription_name
43
+ }
20
44
  end
21
45
 
22
46
  private
23
47
 
24
48
  def failure(expected, actual)
25
- Either::Left.new(message(expected, actual))
49
+ Either::Left.new(failure_message(expected, actual))
26
50
  end
27
51
 
28
- # ignore :reek:UtilityFunction
29
52
  def success
30
- # masked by soft fail
31
- Either::Right.new(nil)
53
+ Either::Right.new(self)
32
54
  end
33
55
 
34
56
  def subscription_name
35
57
  self.class.name.split('::').last.downcase
36
58
  end
37
59
 
38
- def message(expected, actual)
39
- MESSAGE_FORMAT % {
60
+ def failure_message(expected, actual)
61
+ FAILURE_FORMAT % {
40
62
  actual: actual.any? ? actual.map(&:to_s).join("\n") : '[none]',
41
63
  expected: expected.map(&:to_s).join("\n"),
42
64
  subscription_name: subscription_name
@@ -4,8 +4,6 @@ module Mutant
4
4
  module License
5
5
  class Subscription
6
6
  class Commercial < self
7
- include Concord.new(:authors)
8
-
9
7
  class Author
10
8
  include Concord.new(:email)
11
9
 
@@ -20,10 +18,10 @@ module Mutant
20
18
  def apply(world)
21
19
  candidates = candidates(world)
22
20
 
23
- if (authors & candidates).any?
21
+ if (licensed & candidates).any?
24
22
  success
25
23
  else
26
- failure(authors, candidates)
24
+ failure(licensed, candidates)
27
25
  end
28
26
  end
29
27
 
@@ -4,8 +4,6 @@ module Mutant
4
4
  module License
5
5
  class Subscription
6
6
  class Opensource < self
7
- include Concord.new(:repositories)
8
-
9
7
  class Repository
10
8
  include Concord.new(:host, :path)
11
9
 
@@ -43,10 +41,12 @@ module Mutant
43
41
  private_class_method :parse_url
44
42
  end
45
43
 
46
- private_constant(*constants(false))
47
-
48
44
  def self.from_json(value)
49
- new(value.fetch('repositories').map(&Repository.method(:parse)))
45
+ new(
46
+ value
47
+ .fetch('repositories')
48
+ .map(&Repository.public_method(:parse))
49
+ )
50
50
  end
51
51
 
52
52
  def apply(world)
@@ -59,10 +59,10 @@ module Mutant
59
59
  private
60
60
 
61
61
  def check_subscription(actual)
62
- if (repositories.to_set & actual).any?
62
+ if (licensed.to_set & actual).any?
63
63
  success
64
64
  else
65
- failure(repositories, actual)
65
+ failure(licensed, actual)
66
66
  end
67
67
  end
68
68