Class: DeepCover::InstrumentedCloneReporter

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

Constant Summary collapse

GLOB_ALL_CONTENT =

matches regular files, .files, ..files, but not '.' or '..'

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

Instance Method Summary collapse

Constructor Details

#initialize(**options) ⇒ InstrumentedCloneReporter

Returns a new instance of InstrumentedCloneReporter.


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

def initialize(**options)
  @options = CLI_DEFAULTS.merge(options)
  @root_path = @source_path = Pathname.new('.').expand_path
  if !@root_path.join('Gemfile').exist? && @root_path.dirname.join('Gemfile').exist?
    # E.g. rails/activesupport
    @root_path = @root_path.dirname
  end
  path = Pathname('~/test_deep_cover').expand_path
  if path.exist?
    @dest_root = path.join(@source_path.basename)
    @dest_root.mkpath
  else
    @dest_root = Pathname.new(Dir.mktmpdir('deep_cover_test'))
  end

  gem_relative_path = @source_path.relative_path_from(@root_path)
  @main_path = @dest_root.join(gem_relative_path)
end

Instance Method Details

#clearObject


32
33
34
# File 'lib/deep_cover/instrumented_clone_reporter.rb', line 32

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

#copyObject


36
37
38
39
40
41
# File 'lib/deep_cover/instrumented_clone_reporter.rb', line 36

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

#coverObject


99
100
101
102
103
104
105
106
107
108
# File 'lib/deep_cover/instrumented_clone_reporter.rb', line 99

def cover
  entry_point_path = create_entry_point_file
  Tools.cover_cloned_tree(DeepCover.all_tracked_file_paths,
                          clone_root: @dest_root,
                          original_root: @root_path) do |source|
    source.sub(/\A(#.*\n|\s+)*/) do |header|
      "#{header}require #{entry_point_path.inspect};"
    end
  end
end

#create_entry_point_fileObject


43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/deep_cover/instrumented_clone_reporter.rb', line 43

def create_entry_point_file
  require 'tempfile'

  file = nil
  # Basically creating a Tempfile, but we don't want it to be automatically removed...
  # We can't use `ObjectSpace.undefine_finalizer` because it doesn't appear to work on JRuby.
  # Simplified code straight from `Tempfile#initialize`
  ::Dir::Tmpname.create(['deep_cover_entry_point', '.rb']) do |tmpname|
    file = File.open(tmpname, File::RDWR | File::CREAT | File::EXCL, perm: 0o600)
  end

  template = File.read(DeepCover::CORE_GEM_LIB_DIRECTORY + '/deep_cover/setup/clone_mode_entry_template.rb')

  cache_directory = DeepCover.config.cache_directory.to_s
  tracker_global = DeepCover.config.tracker_global

  # Those are the fake global variables that we actually replace as we copy the template over
  template.gsub!('$_cache_directory', cache_directory.inspect)
  template.gsub!('$_global_name', tracker_global.inspect)
  template.gsub!('$_core_gem_lib_directory', DeepCover::CORE_GEM_LIB_DIRECTORY.inspect)

  file.write(template)
  file.close

  file.path
end

#patchObject


89
90
91
# File 'lib/deep_cover/instrumented_clone_reporter.rb', line 89

def patch
  patch_rubocop
end

#patch_rubocopObject


70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/deep_cover/instrumented_clone_reporter.rb', line 70

def patch_rubocop
  path = @dest_root.join('.rubocop.yml')
  return unless path.exist?
  puts 'Patching .rubocop.yml'
  config = YAML.load(path.read)
  all_cop_excludes = ((config['AllCops'] ||= {})['Exclude'] ||= [])

  # Ensure they end with a '/'
  original_root = File.join(File.expand_path(@root_path), '')
  clone_root = File.join(File.expand_path(@dest_root), '')

  paths_to_ignore = DeepCover.all_tracked_file_paths
  paths_to_ignore.select! { |p| p.start_with?(original_root) }
  paths_to_ignore.map! { |p| p.sub(original_root, clone_root) }

  all_cop_excludes.concat(paths_to_ignore)
  path.write("# This file was modified by DeepCover\n" + YAML.dump(config))
end

#processObject


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

def process
  DeepCover.delete_trackers
  # JRuby has a weird behavior with chdir. You can't use it with system if you already did a Dir.chdir (which
  # we may have done to handle the --change-directory option)...
  Dir.chdir(@main_path) do
    system({'DISABLE_SPRING' => 'true', 'DEEP_COVER_OPTIONS' => nil}, *@options[:command])
    $?.exitstatus
  end
end

#remove_deep_cover_configObject


93
94
95
96
97
# File 'lib/deep_cover/instrumented_clone_reporter.rb', line 93

def remove_deep_cover_config
  path = @dest_root.join('.deep_cover.rb')
  return unless path.exist?
  File.delete(path)
end

#reportObject


120
121
122
123
# File 'lib/deep_cover/instrumented_clone_reporter.rb', line 120

def report
  coverage = Coverage.load
  puts coverage.report(**@options)
end

#runObject


125
126
127
128
129
130
131
132
133
134
# File 'lib/deep_cover/instrumented_clone_reporter.rb', line 125

def run
  clear
  copy
  cover
  patch
  remove_deep_cover_config
  exit_code = process
  report
  exit(exit_code)
end