deep-cover-core 0.6.3.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +4 -0
  3. data/.rspec_all +3 -0
  4. data/.rubocop.yml +1 -0
  5. data/Gemfile +11 -0
  6. data/deep_cover_core.gemspec +46 -0
  7. data/lib/deep-cover.rb +3 -0
  8. data/lib/deep_cover/analyser/base.rb +104 -0
  9. data/lib/deep_cover/analyser/branch.rb +41 -0
  10. data/lib/deep_cover/analyser/covered_code_source.rb +21 -0
  11. data/lib/deep_cover/analyser/function.rb +14 -0
  12. data/lib/deep_cover/analyser/node.rb +54 -0
  13. data/lib/deep_cover/analyser/per_char.rb +38 -0
  14. data/lib/deep_cover/analyser/per_line.rb +41 -0
  15. data/lib/deep_cover/analyser/ruby25_like_branch.rb +211 -0
  16. data/lib/deep_cover/analyser/statement.rb +33 -0
  17. data/lib/deep_cover/analyser/stats.rb +54 -0
  18. data/lib/deep_cover/analyser/subset.rb +27 -0
  19. data/lib/deep_cover/analyser.rb +23 -0
  20. data/lib/deep_cover/auto_run.rb +71 -0
  21. data/lib/deep_cover/autoload_tracker.rb +215 -0
  22. data/lib/deep_cover/backports.rb +22 -0
  23. data/lib/deep_cover/base.rb +117 -0
  24. data/lib/deep_cover/basics.rb +22 -0
  25. data/lib/deep_cover/builtin_takeover.rb +10 -0
  26. data/lib/deep_cover/config.rb +104 -0
  27. data/lib/deep_cover/config_setter.rb +33 -0
  28. data/lib/deep_cover/core_ext/autoload_overrides.rb +112 -0
  29. data/lib/deep_cover/core_ext/coverage_replacement.rb +61 -0
  30. data/lib/deep_cover/core_ext/exec_callbacks.rb +27 -0
  31. data/lib/deep_cover/core_ext/instruction_sequence_load_iseq.rb +32 -0
  32. data/lib/deep_cover/core_ext/load_overrides.rb +19 -0
  33. data/lib/deep_cover/core_ext/require_overrides.rb +28 -0
  34. data/lib/deep_cover/coverage/analysis.rb +42 -0
  35. data/lib/deep_cover/coverage/persistence.rb +84 -0
  36. data/lib/deep_cover/coverage.rb +125 -0
  37. data/lib/deep_cover/covered_code.rb +145 -0
  38. data/lib/deep_cover/custom_requirer.rb +187 -0
  39. data/lib/deep_cover/flag_comment_associator.rb +68 -0
  40. data/lib/deep_cover/load.rb +66 -0
  41. data/lib/deep_cover/memoize.rb +48 -0
  42. data/lib/deep_cover/module_override.rb +39 -0
  43. data/lib/deep_cover/node/arguments.rb +51 -0
  44. data/lib/deep_cover/node/assignments.rb +273 -0
  45. data/lib/deep_cover/node/base.rb +155 -0
  46. data/lib/deep_cover/node/begin.rb +27 -0
  47. data/lib/deep_cover/node/block.rb +61 -0
  48. data/lib/deep_cover/node/branch.rb +32 -0
  49. data/lib/deep_cover/node/case.rb +113 -0
  50. data/lib/deep_cover/node/collections.rb +31 -0
  51. data/lib/deep_cover/node/const.rb +12 -0
  52. data/lib/deep_cover/node/def.rb +40 -0
  53. data/lib/deep_cover/node/empty_body.rb +32 -0
  54. data/lib/deep_cover/node/exceptions.rb +79 -0
  55. data/lib/deep_cover/node/if.rb +73 -0
  56. data/lib/deep_cover/node/keywords.rb +86 -0
  57. data/lib/deep_cover/node/literals.rb +100 -0
  58. data/lib/deep_cover/node/loops.rb +74 -0
  59. data/lib/deep_cover/node/mixin/can_augment_children.rb +65 -0
  60. data/lib/deep_cover/node/mixin/check_completion.rb +18 -0
  61. data/lib/deep_cover/node/mixin/child_can_be_empty.rb +27 -0
  62. data/lib/deep_cover/node/mixin/executed_after_children.rb +15 -0
  63. data/lib/deep_cover/node/mixin/execution_location.rb +66 -0
  64. data/lib/deep_cover/node/mixin/filters.rb +47 -0
  65. data/lib/deep_cover/node/mixin/flow_accounting.rb +71 -0
  66. data/lib/deep_cover/node/mixin/has_child.rb +145 -0
  67. data/lib/deep_cover/node/mixin/has_child_handler.rb +75 -0
  68. data/lib/deep_cover/node/mixin/has_tracker.rb +46 -0
  69. data/lib/deep_cover/node/mixin/is_statement.rb +20 -0
  70. data/lib/deep_cover/node/mixin/rewriting.rb +35 -0
  71. data/lib/deep_cover/node/mixin/wrapper.rb +15 -0
  72. data/lib/deep_cover/node/module.rb +66 -0
  73. data/lib/deep_cover/node/root.rb +20 -0
  74. data/lib/deep_cover/node/send.rb +161 -0
  75. data/lib/deep_cover/node/short_circuit.rb +42 -0
  76. data/lib/deep_cover/node/splat.rb +15 -0
  77. data/lib/deep_cover/node/variables.rb +16 -0
  78. data/lib/deep_cover/node.rb +23 -0
  79. data/lib/deep_cover/parser_ext/range.rb +21 -0
  80. data/lib/deep_cover/problem_with_diagnostic.rb +63 -0
  81. data/lib/deep_cover/reporter/base.rb +68 -0
  82. data/lib/deep_cover/reporter/html/base.rb +14 -0
  83. data/lib/deep_cover/reporter/html/index.rb +59 -0
  84. data/lib/deep_cover/reporter/html/site.rb +68 -0
  85. data/lib/deep_cover/reporter/html/source.rb +136 -0
  86. data/lib/deep_cover/reporter/html/template/assets/32px.png +0 -0
  87. data/lib/deep_cover/reporter/html/template/assets/40px.png +0 -0
  88. data/lib/deep_cover/reporter/html/template/assets/deep_cover.css +291 -0
  89. data/lib/deep_cover/reporter/html/template/assets/deep_cover.css.sass +336 -0
  90. data/lib/deep_cover/reporter/html/template/assets/jquery-3.2.1.min.js +4 -0
  91. data/lib/deep_cover/reporter/html/template/assets/jquery-3.2.1.min.map +1 -0
  92. data/lib/deep_cover/reporter/html/template/assets/jstree.css +1108 -0
  93. data/lib/deep_cover/reporter/html/template/assets/jstree.js +8424 -0
  94. data/lib/deep_cover/reporter/html/template/assets/jstreetable.js +1069 -0
  95. data/lib/deep_cover/reporter/html/template/assets/throbber.gif +0 -0
  96. data/lib/deep_cover/reporter/html/template/index.html.erb +75 -0
  97. data/lib/deep_cover/reporter/html/template/source.html.erb +35 -0
  98. data/lib/deep_cover/reporter/html.rb +15 -0
  99. data/lib/deep_cover/reporter/istanbul.rb +184 -0
  100. data/lib/deep_cover/reporter/text.rb +58 -0
  101. data/lib/deep_cover/reporter/tree/util.rb +86 -0
  102. data/lib/deep_cover/reporter.rb +10 -0
  103. data/lib/deep_cover/tools/blank.rb +25 -0
  104. data/lib/deep_cover/tools/builtin_coverage.rb +55 -0
  105. data/lib/deep_cover/tools/camelize.rb +13 -0
  106. data/lib/deep_cover/tools/content_tag.rb +11 -0
  107. data/lib/deep_cover/tools/covered.rb +9 -0
  108. data/lib/deep_cover/tools/execute_sample.rb +34 -0
  109. data/lib/deep_cover/tools/format.rb +18 -0
  110. data/lib/deep_cover/tools/format_char_cover.rb +19 -0
  111. data/lib/deep_cover/tools/format_generated_code.rb +27 -0
  112. data/lib/deep_cover/tools/indent_string.rb +26 -0
  113. data/lib/deep_cover/tools/merge.rb +16 -0
  114. data/lib/deep_cover/tools/number_lines.rb +22 -0
  115. data/lib/deep_cover/tools/our_coverage.rb +11 -0
  116. data/lib/deep_cover/tools/profiling.rb +68 -0
  117. data/lib/deep_cover/tools/render_template.rb +13 -0
  118. data/lib/deep_cover/tools/require_relative_dir.rb +12 -0
  119. data/lib/deep_cover/tools/scan_match_datas.rb +10 -0
  120. data/lib/deep_cover/tools/silence_warnings.rb +18 -0
  121. data/lib/deep_cover/tools/slice.rb +9 -0
  122. data/lib/deep_cover/tools/strip_heredoc.rb +18 -0
  123. data/lib/deep_cover/tools/truncate_backtrace.rb +32 -0
  124. data/lib/deep_cover/tools.rb +22 -0
  125. data/lib/deep_cover/tracker_bucket.rb +50 -0
  126. data/lib/deep_cover/tracker_hits_per_path.rb +35 -0
  127. data/lib/deep_cover/tracker_storage.rb +76 -0
  128. data/lib/deep_cover/tracker_storage_per_path.rb +34 -0
  129. data/lib/deep_cover/version.rb +5 -0
  130. data/lib/deep_cover.rb +22 -0
  131. metadata +329 -0
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeepCover
4
+ module Tools::IndentString
5
+ # In-place implementation copied from active-support.
6
+ IMPLEMENTATION = ->(amount, indent_string = nil, indent_empty_lines = false) do
7
+ indent_string = indent_string || self[/^[ \t]/] || ' '
8
+ re = indent_empty_lines ? /^/ : /^(?!$)/
9
+ gsub!(re, indent_string * amount)
10
+ end
11
+
12
+ # Same as #indent! from active-support
13
+ # https://github.com/rails/rails/blob/10e1f1f9a129f2f197a44009a99b73b8ff9dbc0d/activesupport/lib/active_support/core_ext/string/indent.rb#L7
14
+ def indent_string!(string, *args)
15
+ string.instance_exec(*args, &IMPLEMENTATION)
16
+ end
17
+
18
+ # Same as #indent from active-support
19
+ # https://github.com/rails/rails/blob/10e1f1f9a129f2f197a44009a99b73b8ff9dbc0d/activesupport/lib/active_support/core_ext/string/indent.rb#L42
20
+ def indent_string(string, *args)
21
+ string = string.dup
22
+ indent_string!(string, *args)
23
+ string
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeepCover
4
+ module Tools::Merge
5
+ def merge(*hashes)
6
+ if hashes.last.is_a?(Symbol)
7
+ oper = hashes.pop
8
+ merge(*hashes) { |a, b| a.public_send(oper, b) }
9
+ elsif !block_given?
10
+ merge(*hashes, &:last)
11
+ else
12
+ hashes.inject { |result, h| result.merge(h) { |key, a, b| yield [a, b] } }
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeepCover
4
+ module Tools::NumberLines
5
+ def number_lines(lines, lineno: 1, bad_linenos: [])
6
+ max_lineno = lineno + lines.size - 1
7
+ nb_lineno_digits = max_lineno.to_s.size
8
+ lines.map.with_index do |line, i|
9
+ cur_lineno = lineno + i
10
+ cur_lineno_s = cur_lineno.to_s.rjust(nb_lineno_digits)
11
+ if bad_linenos.include?(cur_lineno)
12
+ cur_lineno_s = "*#{cur_lineno_s}" unless bad_linenos.empty?
13
+ prefix = Term::ANSIColor.red("#{cur_lineno_s} | ")
14
+ else
15
+ cur_lineno_s = " #{cur_lineno_s}" unless bad_linenos.empty?
16
+ prefix = Term::ANSIColor.white("#{cur_lineno_s} | ")
17
+ end
18
+ "#{prefix}#{line}"
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeepCover
4
+ module Tools::OurCoverage
5
+ def our_coverage(source, filename, lineno, **options)
6
+ covered_code = CoveredCode.new(source: source, path: filename, lineno: lineno)
7
+ Tools.execute_sample(covered_code)
8
+ covered_code.line_coverage(options)[(lineno - 1)..-1]
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'delegate'
4
+
5
+ module DeepCover
6
+ module Tools::Profiling
7
+ # Simple forwarding to implementation
8
+ def start
9
+ profiler.start
10
+ end
11
+
12
+ def stop
13
+ @results = profiler.stop
14
+ end
15
+
16
+ def pause
17
+ profiler.pause
18
+ end
19
+
20
+ def resume
21
+ profiler.resume
22
+ end
23
+
24
+ def report
25
+ profiler.report(@results)
26
+ end
27
+
28
+ # Basic utilities using forwarding methods
29
+ def profile(do_start = true)
30
+ return yield unless do_start
31
+ start
32
+ yield
33
+ stop
34
+ report
35
+ end
36
+
37
+ def dont_profile
38
+ pause if profiler_loaded?
39
+ yield
40
+ ensure
41
+ resume if profiler_loaded?
42
+ end
43
+
44
+ def profiler_loaded?
45
+ !!@profiler
46
+ end
47
+
48
+ private
49
+
50
+ # Dependency injection
51
+ def profiler
52
+ @profiler = RubyProfProfiler.new
53
+ end
54
+
55
+ class RubyProfProfiler < SimpleDelegator
56
+ def initialize
57
+ raise 'Profiling is not available when using JRuby' if RUBY_PLATFORM == 'java'
58
+ require 'ruby-prof'
59
+ super(RubyProf)
60
+ end
61
+
62
+ def report(results)
63
+ printer = RubyProf::GraphPrinter.new(results)
64
+ printer.print(STDOUT, {})
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeepCover
4
+ module Tools::RenderTemplate
5
+ def render_template(template, bound_object)
6
+ require 'erb'
7
+ caller_path = Pathname.new(caller(1..1).first.partition(/\.rb:\d/).first).dirname
8
+ template = caller_path.join("template/#{template}.html.erb").read
9
+ erb = ERB.new(template)
10
+ erb.result(bound_object.instance_eval { binding })
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeepCover
4
+ module Tools::RequireRelativeDir
5
+ def require_relative_dir(dir_name, except: [])
6
+ dir = File.dirname(caller(1..1).first.partition(/\.rb:\d/).first)
7
+ Dir["#{dir}/#{dir_name}/*.rb"].sort.each do |file|
8
+ require file unless except.include? File.basename(file, '.rb')
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeepCover
4
+ module Tools::RequireRelativeDir
5
+ # Like String#scan, but return the MatchData object instead
6
+ def scan_match_datas(source, matcher)
7
+ source.to_enum(:scan, matcher).map { Regexp.last_match }
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeepCover
4
+ module Tools::SilenceWarnings
5
+ # copied from: activesupport/lib/active_support/core_ext/kernel/reporting.rb
6
+ def silence_warnings
7
+ with_warnings(nil) { yield }
8
+ end
9
+
10
+ def with_warnings(flag)
11
+ old_verbose = $VERBOSE
12
+ $VERBOSE = flag
13
+ yield
14
+ ensure
15
+ $VERBOSE = old_verbose
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeepCover
4
+ module Tools::Slice
5
+ def slice(hash, *keys)
6
+ keys.each_with_object({}) { |k, h| h[k] = hash[k] if hash.has_key?(k) }
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeepCover
4
+ module Tools::StripHeredoc
5
+ # In-place implementation copied from active-support.
6
+ IMPLEMENTATION = -> do
7
+ gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, ''.freeze).tap do |stripped|
8
+ stripped.freeze if frozen?
9
+ end
10
+ end
11
+
12
+ # Same as #strip_heredoc from active-support
13
+ # https://github.com/rails/rails/blob/16574409f813e2197f88e4a06b527618d64d9ff0/activesupport/lib/active_support/core_ext/string/strip.rb#L22
14
+ def strip_heredoc(string)
15
+ string.instance_exec(&IMPLEMENTATION)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeepCover
4
+ module Tools::TruncateBacktrace
5
+ def truncate_backtrace(backtrace, extra_context: 10)
6
+ backtrace = backtrace.backtrace if backtrace.is_a?(Exception)
7
+ trace_lines = backtrace.uniq
8
+
9
+ keep_from_begin = 0
10
+ keep_from_end = backtrace.size - 1
11
+
12
+ trace_lines.each do |line|
13
+ from_begin = backtrace.index(line)
14
+ from_end = backtrace.rindex(line)
15
+ if from_begin <= backtrace.size - 1 - from_end
16
+ keep_from_begin = [keep_from_begin, from_begin].max
17
+ else
18
+ keep_from_end = [keep_from_end, from_end].min
19
+ end
20
+ end
21
+
22
+ keep_from_begin += extra_context
23
+ keep_from_end -= extra_context
24
+
25
+ return backtrace if keep_from_begin + 5 >= keep_from_end
26
+
27
+ result = backtrace[0..keep_from_begin]
28
+ result << "... #{keep_from_end - keep_from_begin - 1} levels..."
29
+ result.concat backtrace[keep_from_end..-1]
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeepCover
4
+ module Tools
5
+ end
6
+
7
+ require_relative 'tools/require_relative_dir'
8
+ extend Tools::RequireRelativeDir
9
+ require_relative 'tools/silence_warnings'
10
+ extend Tools::SilenceWarnings
11
+ require_relative_dir 'tools'
12
+
13
+ # The functions defined in the submodules of Tools can be accessed
14
+ # either by extending the desired module, or all of them by extending
15
+ # Tools, or by calling them directly Tool.my_function.
16
+ module Tools
17
+ constants.each do |module_name|
18
+ include const_get(module_name)
19
+ end
20
+ extend self
21
+ end
22
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeepCover
4
+ bootstrap
5
+
6
+ require_relative 'tracker_storage'
7
+
8
+ # A holder for TrackerStorages, using some `global_name`.
9
+ class TrackerBucket
10
+ @@index = {}
11
+
12
+ def self.[](global_name)
13
+ raise ArgumentError, "'#{global_name}' is not a valid global name" unless global_name.start_with? '$'
14
+ @@index[global_name] ||= new(global_name)
15
+ end
16
+
17
+ def setup_source
18
+ "#{source} ||= {}"
19
+ end
20
+
21
+ def source
22
+ @global_name
23
+ end
24
+
25
+ class << self
26
+ alias_method :_load, :[]
27
+ private :_load, :new
28
+ end
29
+
30
+ def inspect
31
+ %{#<DeepCover::TrackerBucket "#{@global_name}">}
32
+ end
33
+
34
+ def create_storage(index = nil)
35
+ index ||= @global.size
36
+ TrackerStorage.new(bucket: self, array: @global[index] ||= [], index: index)
37
+ end
38
+
39
+ private
40
+
41
+ def initialize(global_name)
42
+ @global_name = global_name
43
+ @global = eval(setup_source) # rubocop:disable Security/Eval
44
+ end
45
+
46
+ def _dump(_level)
47
+ @global_name
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeepCover
4
+ bootstrap
5
+
6
+ # Should be seen as a hash like {path => tracker_hits, ...},
7
+ # where tracker_hits is simply an array of integers returned from
8
+ # TrackerStorage#tracker_hits.
9
+ # Make it easier to separate some concerns, as well as marshalling.
10
+ #
11
+ class TrackerHitsPerPath
12
+ extend Forwardable
13
+ def_delegators :@index, :each, :each_key, :map, :transform_values, :to_h, :to_hash
14
+
15
+ def initialize(index = {})
16
+ @index = index
17
+ end
18
+
19
+ def [](val)
20
+ @index[val] ||= []
21
+ end
22
+
23
+ def merge!(tracker_hits_per_path)
24
+ @index.merge!(tracker_hits_per_path) { |_h, actual, to_merge| merge_tracker_hits(actual, to_merge) }
25
+ self
26
+ end
27
+
28
+ private def merge_tracker_hits(hits, to_merge)
29
+ unless hits.size == to_merge.size
30
+ raise "Attempting to merge trackers of different sizes: #{hits.size} vs #{to_merge.size}"
31
+ end
32
+ hits.map!.with_index { |val, i| val + to_merge[i] }
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeepCover
4
+ bootstrap
5
+
6
+ # List of allocated trackers from a bucket.
7
+ # Should be thought of as a simple array of integers with
8
+ # a limited interface.
9
+ class TrackerBucket
10
+ class TrackerStorage
11
+ extend Forwardable
12
+ def_delegators :@array, :[], :size, :each, :map, :fetch
13
+
14
+ attr_reader :bucket
15
+
16
+ def initialize(bucket:, array:, index:)
17
+ @bucket = bucket
18
+ @array = array
19
+ @index = index
20
+ @allocated = 0
21
+ end
22
+
23
+ # Returns a range of tracker ids
24
+ def allocate_trackers(nb_needed)
25
+ prev = @allocated
26
+ @allocated += nb_needed
27
+ missing = @allocated - @array.size
28
+ @array.concat(Array.new(missing, 0)) if missing > 0
29
+ prev...@allocated
30
+ end
31
+
32
+ def setup_source
33
+ "(#{bucket.setup_source})[#{@index}]||=Array.new(#{size},0)"
34
+ end
35
+
36
+ def tracker_source(tracker_id)
37
+ "#{bucket.source}[#{@index}][#{tracker_id}]+=1"
38
+ end
39
+
40
+ def tracker_hits
41
+ @array.dup.freeze
42
+ end
43
+
44
+ def tracker_hits=(new_hits)
45
+ if new_hits.size != @array.size
46
+ warn 'Replacing tracker hits with array of different size'
47
+ end
48
+ @array.replace(new_hits)
49
+ end
50
+
51
+ private
52
+
53
+ def dump
54
+ {bucket: @bucket, index: @index, size: @array.size}
55
+ end
56
+
57
+ def _dump(_level)
58
+ Marshal.dump(dump)
59
+ end
60
+
61
+ class << self
62
+ private def load(bucket:, index:, size:)
63
+ storage = bucket.create_storage(index)
64
+ storage.allocate_trackers(size - storage.size)
65
+ storage
66
+ end
67
+
68
+ private def _load(data)
69
+ load(Marshal.load(data)) # rubocop:disable Security/MarshalLoad
70
+ end
71
+ end
72
+ end
73
+
74
+ private_constant :TrackerStorage
75
+ end
76
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeepCover
4
+ bootstrap
5
+
6
+ # Should be seen as a hash like {path => tracker_storage, ...}
7
+ # Make it easier to separate some concerns, as well as marshalling
8
+ #
9
+ class TrackerStoragePerPath
10
+ extend Forwardable
11
+ def_delegators :@index, :each, :each_key, :map, :transform_values
12
+
13
+ attr_reader :bucket
14
+
15
+ def initialize(bucket)
16
+ @bucket = bucket
17
+ @index = {}
18
+ end
19
+
20
+ def [](path)
21
+ @index[path] ||= @bucket.create_storage
22
+ end
23
+
24
+ def tracker_hits_per_path
25
+ TrackerHitsPerPath.new(@index.transform_values(&:tracker_hits))
26
+ end
27
+
28
+ def tracker_hits_per_path=(tracker_hits_per_path)
29
+ tracker_hits_per_path.each do |path, tracker_hits|
30
+ self[path].tracker_hits = tracker_hits
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeepCover
4
+ VERSION = '0.6.3.pre'
5
+ end
data/lib/deep_cover.rb ADDED
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeepCover
4
+ require_relative 'deep_cover/load'
5
+
6
+ load_absolute_basics
7
+
8
+ extend Base
9
+ extend ConfigSetter
10
+ end
11
+ DeepCover::GLOBAL_BINDING = binding
12
+
13
+ require './.deep_cover.rb' if File.exist?('./.deep_cover.rb')
14
+
15
+ if ENV['DEEP_COVER_OPTIONS']
16
+ DeepCover.config.set(YAML.load(ENV['DEEP_COVER_OPTIONS']))
17
+ end
18
+ if %w[1 t true].include?(ENV['DEEP_COVER'])
19
+ DeepCover.start
20
+ require_relative 'deep_cover/auto_run'
21
+ DeepCover::AutoRun.run!('.').report!(**DeepCover.config)
22
+ end