deep-cover 0.1.16 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +3 -8
- data/.travis.yml +4 -4
- data/CHANGELOG.md +10 -0
- data/Gemfile +3 -1
- data/README.md +9 -4
- data/Rakefile +6 -3
- data/deep_cover.gemspec +2 -2
- data/lib/deep_cover.rb +10 -0
- data/lib/deep_cover/analyser.rb +1 -2
- data/lib/deep_cover/analyser/base.rb +32 -0
- data/lib/deep_cover/analyser/branch.rb +19 -4
- data/lib/deep_cover/analyser/node.rb +52 -0
- data/lib/deep_cover/analyser/per_char.rb +18 -1
- data/lib/deep_cover/analyser/stats.rb +54 -0
- data/lib/deep_cover/backports.rb +1 -0
- data/lib/deep_cover/base.rb +17 -1
- data/lib/deep_cover/builtin_takeover.rb +5 -0
- data/lib/deep_cover/cli/deep_cover.rb +2 -1
- data/lib/deep_cover/cli/instrumented_clone_reporter.rb +12 -10
- data/lib/deep_cover/config.rb +22 -8
- data/lib/deep_cover/core_ext/coverage_replacement.rb +22 -18
- data/lib/deep_cover/coverage.rb +3 -203
- data/lib/deep_cover/coverage/analysis.rb +36 -0
- data/lib/deep_cover/coverage/base.rb +91 -0
- data/lib/deep_cover/coverage/istanbul.rb +34 -0
- data/lib/deep_cover/coverage/persistence.rb +93 -0
- data/lib/deep_cover/covered_code.rb +12 -22
- data/lib/deep_cover/custom_requirer.rb +6 -2
- data/lib/deep_cover/node/base.rb +1 -1
- data/lib/deep_cover/node/case.rb +13 -2
- data/lib/deep_cover/node/exceptions.rb +2 -2
- data/lib/deep_cover/node/if.rb +21 -2
- data/lib/deep_cover/node/mixin/flow_accounting.rb +1 -0
- data/lib/deep_cover/node/send.rb +9 -2
- data/lib/deep_cover/node/short_circuit.rb +10 -0
- data/lib/deep_cover/parser_ext/range.rb +4 -4
- data/lib/deep_cover/reporter/html.rb +15 -0
- data/lib/deep_cover/reporter/html/base.rb +14 -0
- data/lib/deep_cover/reporter/html/index.rb +78 -0
- data/lib/deep_cover/reporter/html/site.rb +78 -0
- data/lib/deep_cover/reporter/html/source.rb +136 -0
- data/lib/deep_cover/reporter/html/template/assets/32px.png +0 -0
- data/lib/deep_cover/reporter/html/template/assets/40px.png +0 -0
- data/lib/deep_cover/reporter/html/template/assets/deep_cover.css.sass +338 -0
- data/lib/deep_cover/reporter/html/template/assets/jquery-3.2.1.min.js +4 -0
- data/lib/deep_cover/reporter/html/template/assets/jquery-3.2.1.min.map +1 -0
- data/lib/deep_cover/reporter/html/template/assets/jstree.css +1108 -0
- data/lib/deep_cover/reporter/html/template/assets/jstree.js +8424 -0
- data/lib/deep_cover/reporter/html/template/assets/jstreetable.js +1069 -0
- data/lib/deep_cover/reporter/html/template/assets/throbber.gif +0 -0
- data/lib/deep_cover/reporter/html/template/index.html.erb +75 -0
- data/lib/deep_cover/reporter/html/template/source.html.erb +35 -0
- data/lib/deep_cover/reporter/html/tree.rb +55 -0
- data/lib/deep_cover/tools/content_tag.rb +11 -0
- data/lib/deep_cover/tools/covered.rb +9 -0
- data/lib/deep_cover/tools/merge.rb +16 -0
- data/lib/deep_cover/tools/render_template.rb +13 -0
- data/lib/deep_cover/tools/transform_keys.rb +9 -0
- data/lib/deep_cover/version.rb +1 -1
- metadata +33 -7
- data/lib/deep_cover/analyser/ignore_uncovered.rb +0 -21
- data/lib/deep_cover/analyser/optionally_covered.rb +0 -19
@@ -40,11 +40,12 @@ module DeepCover
|
|
40
40
|
o.separator ''
|
41
41
|
o.string '-o', '--output', 'output folder', default: './coverage'
|
42
42
|
o.string '-c', '--command', 'command to run tests', default: 'bundle exec rake'
|
43
|
+
o.string '--reporter', 'reporter', default: 'html'
|
43
44
|
o.bool '--bundle', 'run bundle before the tests', default: true
|
44
45
|
o.bool '--process', 'turn off to only redo the reporting', default: true
|
45
46
|
o.bool '--open', 'open the output coverage', default: false
|
46
47
|
o.separator 'Coverage options'
|
47
|
-
@ignore_uncovered_map = Analyser.optionally_covered.map do |option|
|
48
|
+
@ignore_uncovered_map = Analyser::Node.optionally_covered.map do |option|
|
48
49
|
default = Config::DEFAULTS[:ignore_uncovered].include?(option)
|
49
50
|
o.bool "--ignore-#{Tools.dasherize(option)}", '', default: default
|
50
51
|
[:"ignore_#{option}", option]
|
@@ -106,23 +106,25 @@ module DeepCover
|
|
106
106
|
|
107
107
|
def patch_gemfile
|
108
108
|
gemfile = @dest_root.join('Gemfile')
|
109
|
+
deps = Bundler::Definition.build(gemfile, nil, nil).dependencies
|
110
|
+
|
111
|
+
return if deps.find { |e| e.name == 'deep-cover' }
|
112
|
+
|
109
113
|
content = File.read(gemfile)
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
].join("\n"))
|
118
|
-
end
|
114
|
+
puts "Patching Gemfile #{gemfile}"
|
115
|
+
File.write(gemfile, [
|
116
|
+
'# This file was modified by DeepCover',
|
117
|
+
content,
|
118
|
+
"gem 'deep-cover', path: '#{File.expand_path(__dir__ + '/../../../')}'",
|
119
|
+
'',
|
120
|
+
].join("\n"))
|
119
121
|
end
|
120
122
|
|
121
123
|
def patch_rubocop
|
122
124
|
path = @dest_root.join('.rubocop.yml')
|
123
125
|
return unless path.exist?
|
124
126
|
puts 'Patching .rubocop.yml'
|
125
|
-
config = YAML.
|
127
|
+
config = YAML.load(path.read.gsub(/(?<!\w)lib(?!\w)/, 'lib_original'))
|
126
128
|
((config['AllCops'] ||= {})['Exclude'] ||= []) << 'lib/**/*' << 'app/**/*'
|
127
129
|
path.write("# This file was modified by DeepCover\n" + YAML.dump(config))
|
128
130
|
end
|
data/lib/deep_cover/config.rb
CHANGED
@@ -14,38 +14,52 @@ module DeepCover
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def to_hash
|
17
|
-
|
17
|
+
@options.dup
|
18
18
|
end
|
19
19
|
alias_method :to_h, :to_hash
|
20
20
|
|
21
21
|
def ignore_uncovered(*keywords)
|
22
|
-
|
23
|
-
|
22
|
+
if keywords.empty?
|
23
|
+
@options[:ignore_uncovered]
|
24
|
+
else
|
25
|
+
check_uncovered(keywords)
|
26
|
+
change(:ignore_uncovered, @options[:ignore_uncovered] | keywords)
|
27
|
+
end
|
24
28
|
end
|
25
29
|
|
26
30
|
def detect_uncovered(*keywords)
|
27
|
-
|
28
|
-
|
31
|
+
if keywords.empty?
|
32
|
+
Analyser::Node.optionally_covered - @options[:ignore_uncovered]
|
33
|
+
else
|
34
|
+
check_uncovered(keywords)
|
35
|
+
change(:ignore_uncovered, @options[:ignore_uncovered] - keywords)
|
36
|
+
end
|
29
37
|
end
|
30
38
|
|
31
39
|
def paths(paths = nil)
|
32
40
|
if paths
|
33
|
-
change(:paths, Array(paths).dup
|
41
|
+
change(:paths, Array(paths).dup)
|
34
42
|
else
|
35
43
|
@options[:paths]
|
36
44
|
end
|
37
45
|
end
|
38
46
|
|
47
|
+
def reset
|
48
|
+
DEFAULTS.each do |key, value|
|
49
|
+
change(key, value)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
39
53
|
private
|
40
54
|
|
41
55
|
def check_uncovered(keywords)
|
42
|
-
unknown = keywords - Analyser.optionally_covered
|
56
|
+
unknown = keywords - Analyser::Node.optionally_covered
|
43
57
|
raise ArgumentError, "unknown options: #{unknown.join(', ')}" unless unknown.empty?
|
44
58
|
end
|
45
59
|
|
46
60
|
def change(option, value)
|
47
61
|
if @options[option] != value
|
48
|
-
@options[option] = value
|
62
|
+
@options[option] = value.freeze
|
49
63
|
@notify.config_changed(option) if @notify.respond_to? :config_changed
|
50
64
|
end
|
51
65
|
self
|
@@ -2,27 +2,31 @@
|
|
2
2
|
|
3
3
|
# This is a complete replacement for the builtin Coverage module of Ruby
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
module DeepCover
|
6
|
+
module CoverageReplacement
|
7
|
+
class << self
|
8
|
+
def running?
|
9
|
+
DeepCover.running?
|
10
|
+
end
|
8
11
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
12
|
+
def start
|
13
|
+
return if running?
|
14
|
+
DeepCover.start
|
15
|
+
nil
|
16
|
+
end
|
15
17
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
def result
|
19
|
+
r = peek_result
|
20
|
+
DeepCover.stop
|
21
|
+
r
|
22
|
+
end
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
-
|
24
|
+
def peek_result
|
25
|
+
raise 'coverage measurement is not enabled' unless running?
|
26
|
+
DeepCover.coverage.covered_codes.map do |covered_code|
|
27
|
+
[covered_code.path, covered_code.line_coverage(allow_partial: false)]
|
28
|
+
end.to_h
|
29
|
+
end
|
25
30
|
end
|
26
|
-
Hash[results]
|
27
31
|
end
|
28
32
|
end
|
data/lib/deep_cover/coverage.rb
CHANGED
@@ -1,208 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module DeepCover
|
4
|
-
require 'parser'
|
5
|
-
silence_warnings do
|
6
|
-
require 'parser/current'
|
7
|
-
end
|
8
4
|
require_relative 'covered_code'
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
class Coverage
|
13
|
-
include Enumerable
|
14
|
-
|
15
|
-
def initialize(**options)
|
16
|
-
@covered_codes = {}
|
17
|
-
@options = options
|
18
|
-
end
|
19
|
-
|
20
|
-
def covered_codes
|
21
|
-
@covered_codes.dup
|
22
|
-
end
|
23
|
-
|
24
|
-
def reset
|
25
|
-
@covered_codes = {}
|
26
|
-
end
|
27
|
-
|
28
|
-
def line_coverage(filename, **options)
|
29
|
-
covered_code(filename).line_coverage(**options)
|
30
|
-
end
|
31
|
-
|
32
|
-
def covered_code(path, **options)
|
33
|
-
raise 'path must be an absolute path' unless Pathname.new(path).absolute?
|
34
|
-
@covered_codes[path] ||= CoveredCode.new(path: path, **options, **@options)
|
35
|
-
end
|
36
|
-
|
37
|
-
def each
|
38
|
-
return to_enum unless block_given?
|
39
|
-
@covered_codes.each_value { |covered_code| yield covered_code }
|
40
|
-
self
|
41
|
-
end
|
42
|
-
|
43
|
-
def to_istanbul(**options)
|
44
|
-
map do |covered_code|
|
45
|
-
next {} unless covered_code.has_executed?
|
46
|
-
covered_code.to_istanbul(**options)
|
47
|
-
end.inject(:merge)
|
48
|
-
end
|
49
|
-
|
50
|
-
def output_istanbul(dir: '.', name: '.nyc_output', **options)
|
51
|
-
path = Pathname.new(dir).expand_path.join(name)
|
52
|
-
path.mkpath
|
53
|
-
path.each_child(&:delete)
|
54
|
-
path.join('deep_cover.json').write(JSON.pretty_generate(to_istanbul(**options)))
|
55
|
-
path
|
56
|
-
end
|
57
|
-
|
58
|
-
def report_istanbul(output: nil, **options)
|
59
|
-
dir = output_istanbul(**options).dirname
|
60
|
-
unless [nil, '', 'false'].include? output
|
61
|
-
output = File.expand_path(output)
|
62
|
-
html = "--reporter=html --report-dir='#{output}'"
|
63
|
-
if options[:open]
|
64
|
-
html += " && open '#{output}/index.html'"
|
65
|
-
else
|
66
|
-
msg = "\nHTML coverage written to: '#{output}/index.html'"
|
67
|
-
end
|
68
|
-
end
|
69
|
-
`cd #{dir} && nyc report --reporter=text #{html}` + msg.to_s
|
70
|
-
end
|
71
|
-
|
72
|
-
def basic_report
|
73
|
-
missing = map do |covered_code|
|
74
|
-
if covered_code.has_executed?
|
75
|
-
missed = covered_code.line_coverage.each_with_index.map do |line_cov, line_index|
|
76
|
-
line_index + 1 if line_cov == 0
|
77
|
-
end.compact
|
78
|
-
else
|
79
|
-
missed = ['all']
|
80
|
-
end
|
81
|
-
[covered_code.buffer.name, missed] unless missed.empty?
|
82
|
-
end.compact.to_h
|
83
|
-
missing.map do |path, lines|
|
84
|
-
"#{File.basename(path)}: #{lines.join(', ')}"
|
85
|
-
end.join("\n")
|
86
|
-
end
|
87
|
-
|
88
|
-
def report(**options)
|
89
|
-
if Reporter::Istanbul.available?
|
90
|
-
report_istanbul(**options)
|
91
|
-
else
|
92
|
-
warn 'nyc not available. Please install `nyc` using `yarn global add nyc` or `npm i nyc -g`'
|
93
|
-
basic_report
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def self.load(dest_path, dirname = 'deep_cover', with_trackers: true)
|
98
|
-
Persistence.new(dest_path, dirname).load(with_trackers: with_trackers)
|
99
|
-
end
|
100
|
-
|
101
|
-
def self.saved?(dest_path, dirname = 'deep_cover')
|
102
|
-
Persistence.new(dest_path, dirname).saved?
|
103
|
-
end
|
104
|
-
|
105
|
-
def save(dest_path, dirname = 'deep_cover')
|
106
|
-
Persistence.new(dest_path, dirname).save(self)
|
107
|
-
self
|
108
|
-
end
|
109
|
-
|
110
|
-
def save_trackers(dest_path, dirname = 'deep_cover')
|
111
|
-
Persistence.new(dest_path, dirname).save_trackers(tracker_global)
|
112
|
-
self
|
113
|
-
end
|
114
|
-
|
115
|
-
def tracker_global
|
116
|
-
@options.fetch(:tracker_global, CoveredCode::DEFAULT_TRACKER_GLOBAL)
|
117
|
-
end
|
118
|
-
|
119
|
-
class Persistence
|
120
|
-
# rubocop:disable Security/MarshalLoad
|
121
|
-
BASENAME = 'coverage.dc'
|
122
|
-
TRACKER_TEMPLATE = 'trackers%{unique}.dct'
|
123
|
-
|
124
|
-
attr_reader :dir_path
|
125
|
-
def initialize(dest_path, dirname)
|
126
|
-
@dir_path = Pathname(dest_path).join(dirname).expand_path
|
127
|
-
end
|
128
|
-
|
129
|
-
def load(with_trackers: true)
|
130
|
-
saved?
|
131
|
-
load_trackers if with_trackers
|
132
|
-
load_coverage
|
133
|
-
end
|
134
|
-
|
135
|
-
def save(coverage)
|
136
|
-
create_if_needed
|
137
|
-
delete_trackers
|
138
|
-
save_coverage(coverage)
|
139
|
-
end
|
140
|
-
|
141
|
-
def save_trackers(global)
|
142
|
-
saved?
|
143
|
-
trackers = eval(global) # rubocop:disable Security/Eval
|
144
|
-
# Some testing involves more than one process, some of which don't run any of our covered code.
|
145
|
-
# Don't save anything if that's the case
|
146
|
-
return if trackers.nil?
|
147
|
-
basename = format(TRACKER_TEMPLATE, unique: SecureRandom.urlsafe_base64)
|
148
|
-
dir_path.join(basename).binwrite(Marshal.dump(
|
149
|
-
version: DeepCover::VERSION,
|
150
|
-
global: global,
|
151
|
-
trackers: trackers,
|
152
|
-
))
|
153
|
-
end
|
154
|
-
|
155
|
-
def saved?
|
156
|
-
raise "Can't find folder '#{dir_path}'" unless dir_path.exist?
|
157
|
-
self
|
158
|
-
end
|
159
|
-
|
160
|
-
private
|
161
|
-
|
162
|
-
def create_if_needed
|
163
|
-
dir_path.mkpath
|
164
|
-
end
|
165
|
-
|
166
|
-
def save_coverage(coverage)
|
167
|
-
dir_path.join(BASENAME).binwrite(Marshal.dump(
|
168
|
-
version: DeepCover::VERSION,
|
169
|
-
coverage: coverage,
|
170
|
-
))
|
171
|
-
end
|
172
|
-
|
173
|
-
def load_coverage
|
174
|
-
Marshal.load(dir_path.join(BASENAME).binread).tap do |version: raise, coverage: raise|
|
175
|
-
raise "dump version mismatch: #{version}, currently #{DeepCover::VERSION}" unless version == DeepCover::VERSION
|
176
|
-
return coverage
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
def load_trackers
|
181
|
-
tracker_files.each do |full_path|
|
182
|
-
Marshal.load(full_path.binread).tap do |version: raise, global: raise, trackers: raise|
|
183
|
-
raise "dump version mismatch: #{version}, currently #{DeepCover::VERSION}" unless version == DeepCover::VERSION
|
184
|
-
merge_trackers(eval("#{global} ||= {}"), trackers) # rubocop:disable Security/Eval
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
def merge_trackers(hash, to_merge)
|
190
|
-
hash.merge!(to_merge) do |_key, current, to_add|
|
191
|
-
unless current.empty? || current.size == to_add.size
|
192
|
-
warn "Merging trackers of different sizes: #{current.size} vs #{to_add.size}"
|
193
|
-
end
|
194
|
-
to_add.zip(current).map { |a, b| a + b }
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
def tracker_files
|
199
|
-
basename = format(TRACKER_TEMPLATE, unique: '*')
|
200
|
-
Pathname.glob(dir_path.join(basename))
|
201
|
-
end
|
202
|
-
|
203
|
-
def delete_trackers
|
204
|
-
tracker_files.each(&:delete)
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
5
|
+
Coverage = Class.new
|
6
|
+
require_relative_dir 'coverage'
|
7
|
+
Coverage.include Coverage::Istanbul
|
208
8
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DeepCover
|
4
|
+
class Coverage::Analysis < Struct.new(:covered_codes, :options)
|
5
|
+
include Memoize
|
6
|
+
memoize :analyser_map, :stat_map
|
7
|
+
|
8
|
+
def analyser_map
|
9
|
+
covered_codes.map do |covered_code|
|
10
|
+
[covered_code, compute_analysers(covered_code)]
|
11
|
+
end.to_h
|
12
|
+
end
|
13
|
+
|
14
|
+
def stat_map
|
15
|
+
analyser_map.transform_values { |a| a.transform_values(&:stats) }
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def compute_analysers(covered_code)
|
21
|
+
base = Analyser::Node.new(covered_code, **options)
|
22
|
+
{node: base}.merge!(
|
23
|
+
{
|
24
|
+
per_char: Analyser::PerChar,
|
25
|
+
branch: Analyser::Branch,
|
26
|
+
}.transform_values { |klass| klass.new(base, **options) }
|
27
|
+
)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Coverage
|
32
|
+
def analysis(**options)
|
33
|
+
Analysis.new(covered_codes, options)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DeepCover
|
4
|
+
# A collection of CoveredCode
|
5
|
+
class Coverage
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
def initialize(**options)
|
9
|
+
@covered_code_index = {}
|
10
|
+
@options = options
|
11
|
+
end
|
12
|
+
|
13
|
+
def covered_codes
|
14
|
+
@covered_code_index.values
|
15
|
+
end
|
16
|
+
|
17
|
+
def reset
|
18
|
+
@covered_code_index = {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def line_coverage(filename, **options)
|
22
|
+
covered_code(filename).line_coverage(**options)
|
23
|
+
end
|
24
|
+
|
25
|
+
def covered_code(path, **options)
|
26
|
+
raise 'path must be an absolute path' unless Pathname.new(path).absolute?
|
27
|
+
@covered_code_index[path] ||= CoveredCode.new(path: path, **options, **@options)
|
28
|
+
end
|
29
|
+
|
30
|
+
def each
|
31
|
+
return to_enum unless block_given?
|
32
|
+
@covered_code_index.each_value { |covered_code| yield covered_code }
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def report(**options)
|
37
|
+
case (reporter = options.fetch(:reporter, :html).to_sym)
|
38
|
+
when :html
|
39
|
+
Reporter::HTML.report(self, **options)
|
40
|
+
when :istanbul
|
41
|
+
if Reporter::Istanbul.available?
|
42
|
+
report_istanbul(**options)
|
43
|
+
else
|
44
|
+
warn 'nyc not available. Please install `nyc` using `yarn global add nyc` or `npm i nyc -g`'
|
45
|
+
end
|
46
|
+
when :text
|
47
|
+
basic_report
|
48
|
+
else
|
49
|
+
raise ArgumentError, "Unknown reporter: #{reporter}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def basic_report
|
54
|
+
missing = map do |covered_code|
|
55
|
+
if covered_code.has_executed?
|
56
|
+
missed = covered_code.line_coverage.each_with_index.map do |line_cov, line_index|
|
57
|
+
line_index + 1 if line_cov == 0
|
58
|
+
end.compact
|
59
|
+
else
|
60
|
+
missed = ['all']
|
61
|
+
end
|
62
|
+
[covered_code.buffer.name, missed] unless missed.empty?
|
63
|
+
end.compact.to_h
|
64
|
+
missing.map do |path, lines|
|
65
|
+
"#{File.basename(path)}: #{lines.join(', ')}"
|
66
|
+
end.join("\n")
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.load(dest_path, dirname = 'deep_cover', with_trackers: true)
|
70
|
+
Persistence.new(dest_path, dirname).load(with_trackers: with_trackers)
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.saved?(dest_path, dirname = 'deep_cover')
|
74
|
+
Persistence.new(dest_path, dirname).saved?
|
75
|
+
end
|
76
|
+
|
77
|
+
def save(dest_path, dirname = 'deep_cover')
|
78
|
+
Persistence.new(dest_path, dirname).save(self)
|
79
|
+
self
|
80
|
+
end
|
81
|
+
|
82
|
+
def save_trackers(dest_path, dirname = 'deep_cover')
|
83
|
+
Persistence.new(dest_path, dirname).save_trackers(tracker_global)
|
84
|
+
self
|
85
|
+
end
|
86
|
+
|
87
|
+
def tracker_global
|
88
|
+
@options.fetch(:tracker_global, CoveredCode::DEFAULT_TRACKER_GLOBAL)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|