Class: DeepCover::CLI::InstrumentedCloneReporter

Inherits:
Object
  • Object
show all
Includes:
Tools
Defined in:
lib/deep_cover/cli/instrumented_clone_reporter.rb

Defined Under Namespace

Modules: Gem, GemCollection, Rails, SingleGem

Constant Summary collapse

GLOB_ALL_CONTENT =

matches regular files, .files, ..files, but not ‘.’ or ‘..’

'{,.[^.],..?}*'

Instance Method Summary collapse

Constructor Details

#initialize(source_path, command: 'rake', **options) ⇒ InstrumentedCloneReporter

Returns a new instance of InstrumentedCloneReporter.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/deep_cover/cli/instrumented_clone_reporter.rb', line 13

def initialize(source_path, command: 'rake', **options)
  @command = command
  @options = options
  @root_path = @source_path = Pathname.new(source_path).expand_path
  unless @root_path.join('Gemfile').exist?
    # E.g. rails/activesupport
    @root_path = @root_path.dirname
    raise "Can't find Gemfile" unless @root_path.join('Gemfile').exist?
  end
  @dest_root = Pathname('~/test_deep_cover').expand_path
  @dest_root = Pathname.new(Dir.mktmpdir('deep_cover_test')) unless @dest_root.exist?

  gem_relative_path = @source_path.relative_path_from(@root_path)
  @main_path = @dest_root.join(gem_relative_path)
  singleton_class.include self.class.const_get(Tools.camelize(style))
end

Instance Method Details

#bundleObject



159
160
161
162
163
164
# File 'lib/deep_cover/cli/instrumented_clone_reporter.rb', line 159

def bundle
  puts 'Running `bundle install`'
  Bundler.with_clean_env do
    `cd #{@dest_root} && bundle`
  end
end

#clearObject



30
31
32
# File 'lib/deep_cover/cli/instrumented_clone_reporter.rb', line 30

def clear
  FileUtils.rm_rf(Dir.glob("#{@dest_root}/#{GLOB_ALL_CONTENT}"))
end

#copyObject



34
35
36
37
38
39
# File 'lib/deep_cover/cli/instrumented_clone_reporter.rb', line 34

def copy
  return true if @copied
  puts 'Cloning...'
  FileUtils.cp_r(Dir.glob("#{@root_path}/#{GLOB_ALL_CONTENT}"), @dest_root)
  @copied = true
end

#coverObject



136
137
138
139
140
141
142
143
144
145
146
# File 'lib/deep_cover/cli/instrumented_clone_reporter.rb', line 136

def cover
  coverage = Coverage.new
  each_dir_to_cover do |to_cover|
    original = to_cover.sub_ext('_original')
    FileUtils.cp_r(to_cover, original)
    Tools.dump_covered_code(original,
                            coverage: coverage, root_path: @dest_root.to_s,
                            dest_path: to_cover)
  end
  coverage.save(@dest_root.to_s)
end

#patchObject



130
131
132
133
134
# File 'lib/deep_cover/cli/instrumented_clone_reporter.rb', line 130

def patch
  patch_gemfile
  patch_rubocop
  patch_main_ruby_files
end

#patch_gemfileObject



107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/deep_cover/cli/instrumented_clone_reporter.rb', line 107

def patch_gemfile
  gemfile = @dest_root.join('Gemfile')
  content = File.read(gemfile)
  unless content =~ /gem 'deep-cover'/
    puts "Patching Gemfile #{gemfile}"
    File.write(gemfile, [
                          '# This file was modified by DeepCover',
                          content,
                          "gem 'deep-cover', path: '#{File.expand_path(__dir__ + '/../../../')}'",
                          '',
                        ].join("\n"))
  end
end

#patch_main_ruby_filesObject

Back to global functionality



100
101
102
103
104
105
# File 'lib/deep_cover/cli/instrumented_clone_reporter.rb', line 100

def patch_main_ruby_files
  each_main_ruby_files do |main|
    puts "Patching #{main}"
    patch_ruby_file(main)
  end
end

#patch_rubocopObject



121
122
123
124
125
126
127
128
# File 'lib/deep_cover/cli/instrumented_clone_reporter.rb', line 121

def patch_rubocop
  path = @dest_root.join('.rubocop.yml')
  return unless path.exist?
  puts 'Patching .rubocop.yml'
  config = YAML.safe_load(path.read.gsub(/(?<!\w)lib(?!\w)/, 'lib_original'))
  ((config['AllCops'] ||= {})['Exclude'] ||= []) << 'lib/**/*' << 'app/**/*'
  path.write("# This file was modified by DeepCover\n" + YAML.dump(config))
end

#patch_ruby_file(ruby_file) ⇒ Object



41
42
43
44
45
46
# File 'lib/deep_cover/cli/instrumented_clone_reporter.rb', line 41

def patch_ruby_file(ruby_file)
  content = ruby_file.read
  # Insert our code after leading comments:
  content.sub!(/^(#.*\n+)*/) { |header| "#{header}require 'deep_cover/auto_run';DeepCover::AutoRun.run! '#{@dest_root}';" }
  ruby_file.write(content)
end

#processObject



148
149
150
151
152
# File 'lib/deep_cover/cli/instrumented_clone_reporter.rb', line 148

def process
  Bundler.with_clean_env do
    system("cd #{@main_path} && #{@command}")
  end
end

#reportObject



154
155
156
157
# File 'lib/deep_cover/cli/instrumented_clone_reporter.rb', line 154

def report
  coverage = Coverage.load @dest_root.to_s
  puts coverage.report(dir: @dest_root.to_s, **@options)
end

#runObject



166
167
168
169
170
171
172
173
174
175
176
# File 'lib/deep_cover/cli/instrumented_clone_reporter.rb', line 166

def run
  if @options.fetch(:process, true)
    clear
    copy
    cover
    patch
    bundle if @options.fetch(:bundle, true)
    process
  end
  report
end

#styleObject



48
49
50
51
52
53
54
55
56
# File 'lib/deep_cover/cli/instrumented_clone_reporter.rb', line 48

def style
  if @source_path.join('config/environments/test.rb').exist?
    :rails
  elsif @source_path.join('lib').exist?
    :single_gem
  else # Rails style
    :gem_collection
  end
end