slather 1.8.3 → 2.0.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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.travis.yml +1 -0
  4. data/CHANGELOG.md +21 -1
  5. data/README.md +15 -10
  6. data/README_Images/test_scheme.png +0 -0
  7. data/Rakefile +6 -0
  8. data/bin/slather +45 -6
  9. data/lib/slather/coverage_file.rb +37 -90
  10. data/lib/slather/coverage_info.rb +84 -0
  11. data/lib/slather/coverage_service/cobertura_xml_output.rb +10 -6
  12. data/lib/slather/coverage_service/coveralls.rb +5 -1
  13. data/lib/slather/coverage_service/gutter_json_output.rb +12 -8
  14. data/lib/slather/coverage_service/hardcover.rb +5 -1
  15. data/lib/slather/coverage_service/html_output.rb +32 -19
  16. data/lib/slather/coverage_service/simple_output.rb +5 -1
  17. data/lib/slather/{coveralls_coverage_file.rb → coveralls_coverage.rb} +1 -1
  18. data/lib/slather/profdata_coverage_file.rb +130 -0
  19. data/lib/slather/project.rb +191 -27
  20. data/lib/slather/version.rb +1 -1
  21. data/lib/slather.rb +9 -1
  22. data/slather.gemspec +4 -4
  23. data/spec/fixtures/cobertura.xml +56 -79
  24. data/spec/fixtures/fixtures/Fixtures.swift +15 -0
  25. data/spec/fixtures/fixtures/other_fixtures.m +23 -0
  26. data/spec/fixtures/fixtures_html/Branches.m.html +244 -258
  27. data/spec/fixtures/fixtures_html/BranchesTests.m.html +209 -225
  28. data/spec/fixtures/fixtures_html/fixtures.m.html +134 -148
  29. data/spec/fixtures/fixtures_html/fixturesTests.m.html +199 -213
  30. data/spec/fixtures/fixtures_html/index.html +68 -131
  31. data/spec/fixtures/fixtures_html/peekaviewTests.m.html +189 -203
  32. data/spec/fixtures/gutter.json +1 -1
  33. data/spec/slather/coverage_file_spec.rb +20 -12
  34. data/spec/slather/coverage_service/cobertura_xml_spec.rb +7 -3
  35. data/spec/slather/coverage_service/coveralls_spec.rb +61 -20
  36. data/spec/slather/coverage_service/gutter_json_spec.rb +6 -2
  37. data/spec/slather/coverage_service/hardcover_spec.rb +33 -3
  38. data/spec/slather/coverage_service/html_output_spec.rb +48 -7
  39. data/spec/slather/coverage_service/simple_output_spec.rb +12 -13
  40. data/spec/slather/profdata_coverage_spec.rb +128 -0
  41. data/spec/slather/project_spec.rb +222 -49
  42. data/spec/spec_helper.rb +28 -2
  43. metadata +58 -46
  44. data/spec/fixtures/fixtures_html/Empty.m.html +0 -30
  45. data/spec/fixtures/fixtures_html/fixtures_cpp.cpp.html +0 -30
  46. data/spec/fixtures/fixtures_html/fixtures_m.m.html +0 -30
  47. data/spec/fixtures/fixtures_html/fixtures_mm.mm.html +0 -30
  48. data/spec/fixtures/fixtures_html/peekaview.m.html +0 -190
@@ -5,7 +5,11 @@ module Slather
5
5
  module HtmlOutput
6
6
 
7
7
  def coverage_file_class
8
- Slather::CoverageFile
8
+ if input_format == "profdata"
9
+ Slather::ProfdataCoverageFile
10
+ else
11
+ Slather::CoverageFile
12
+ end
9
13
  end
10
14
  private :coverage_file_class
11
15
 
@@ -46,6 +50,11 @@ module Slather
46
50
  FileUtils.rm_rf(directory_path) if Dir.exist?(directory_path)
47
51
  FileUtils.mkdir_p(directory_path)
48
52
 
53
+ FileUtils.cp(File.join(gem_root_path, "docs/logo.jpg"), directory_path)
54
+ FileUtils.cp(File.join(gem_root_path, "assets/slather.css"), directory_path)
55
+ FileUtils.cp(File.join(gem_root_path, "assets/highlight.pack.js"), directory_path)
56
+ FileUtils.cp(File.join(gem_root_path, "assets/list.min.js"), directory_path)
57
+
49
58
  reports.each do |name, doc|
50
59
  html_file = File.join(directory_path, "#{name}.html")
51
60
  File.write(html_file, doc.to_html)
@@ -141,18 +150,20 @@ module Slather
141
150
  next
142
151
  end
143
152
 
153
+ line_number_separator = coverage_file.line_number_separator
154
+
144
155
  cov.table(:class => "source_code") {
145
156
  cleaned_gcov_lines.each do |line|
146
- data = line.split(':', 3)
157
+ data = line.split(line_number_separator, 3)
147
158
 
148
159
  line_number = data[1].to_i
149
160
  next unless line_number > 0
150
161
 
151
162
  coverage_data = data[0].strip
152
- line_data = [line_number, data[2], hits_for_coverage_data(coverage_data)]
163
+ line_data = [line_number, data[2], hits_for_coverage_line(coverage_file, line)]
153
164
  classes = ["num", "src", "coverage"]
154
165
 
155
- cov.tr(:class => class_for_coverage_data(coverage_data)) {
166
+ cov.tr(:class => class_for_coverage_line(coverage_file,line)) {
156
167
  line_data.each_with_index { |line, idx|
157
168
  if idx != 1
158
169
  cov.td(line, :class => classes[idx])
@@ -171,10 +182,10 @@ module Slather
171
182
  end
172
183
 
173
184
  def generate_html_template(title, is_index, is_file_empty)
174
- logo_path = File.join(gem_root_path, "docs/logo.jpg")
175
- css_path = File.join(gem_root_path, "assets/slather.css")
176
- highlight_js_path = File.join(gem_root_path, "assets/highlight.pack.js")
177
- list_js_path = File.join(gem_root_path, "assets/list.min.js")
185
+ logo_path = "logo.jpg"
186
+ css_path = "slather.css"
187
+ highlight_js_path = "highlight.pack.js"
188
+ list_js_path = "list.min.js"
178
189
 
179
190
  builder = Nokogiri::HTML::Builder.new do |doc|
180
191
  doc.html {
@@ -191,7 +202,7 @@ module Slather
191
202
  doc.div(:class => "row") { doc.div(:id => "reports") }
192
203
  doc.footer {
193
204
  doc.div(:class => "row") {
194
- doc.p { doc.a("Fork me on Github", :href => "https://github.com/venmo/slather") }
205
+ doc.p { doc.a("Fork me on Github", :href => "https://github.com/SlatherOrg/slather") }
195
206
  doc.p("© #{Date.today.year} Slather")
196
207
  }
197
208
  }
@@ -215,19 +226,21 @@ module Slather
215
226
  File.expand_path File.join(File.dirname(__dir__), "../..")
216
227
  end
217
228
 
218
- def class_for_coverage_data(coverage_data)
219
- case coverage_data
220
- when /\d/ then "covered"
221
- when /#/ then "missed"
222
- else "never"
229
+ def class_for_coverage_line(coverage_file, coverage_line)
230
+ hits = coverage_file.coverage_for_line(coverage_line)
231
+ case
232
+ when hits == nil then "never"
233
+ when hits > 0 then "covered"
234
+ else "missed"
223
235
  end
224
236
  end
225
237
 
226
- def hits_for_coverage_data(coverage_data)
227
- case coverage_data
228
- when /\d/ then (coverage_data.to_i > 0) ? "#{coverage_data}x" : ""
229
- when /#/ then "!"
230
- else ""
238
+ def hits_for_coverage_line(coverage_file, coverage_line)
239
+ hits = coverage_file.coverage_for_line(coverage_line)
240
+ case
241
+ when hits == nil then ""
242
+ when hits > 0 then "#{hits}x"
243
+ else "!"
231
244
  end
232
245
  end
233
246
 
@@ -3,7 +3,11 @@ module Slather
3
3
  module SimpleOutput
4
4
 
5
5
  def coverage_file_class
6
- Slather::CoverageFile
6
+ if input_format == "profdata"
7
+ Slather::ProfdataCoverageFile
8
+ else
9
+ Slather::CoverageFile
10
+ end
7
11
  end
8
12
  private :coverage_file_class
9
13
 
@@ -1,5 +1,5 @@
1
1
  module Slather
2
- class CoverallsCoverageFile < CoverageFile
2
+ module CoverallsCoverage
3
3
 
4
4
  def as_json
5
5
  {
@@ -0,0 +1,130 @@
1
+ require 'slather/coverage_info'
2
+ require 'slather/coveralls_coverage'
3
+
4
+ module Slather
5
+ class ProfdataCoverageFile
6
+
7
+ include CoverageInfo
8
+ include CoverallsCoverage
9
+
10
+ attr_accessor :project, :source, :line_data
11
+
12
+ def initialize(project, source)
13
+ self.project = project
14
+ self.source = source
15
+ create_line_data
16
+ end
17
+
18
+ def create_line_data
19
+ all_lines = self.source.split("\n")[1..-1]
20
+ line_data = Hash.new
21
+ all_lines.each { |line| line_data[line_number_in_line(line)] = line }
22
+ self.line_data = line_data
23
+ end
24
+ private :create_line_data
25
+
26
+ def source_file_pathname
27
+ @source_file_pathname ||= begin
28
+ path = self.source.split("\n")[0].sub ":", ""
29
+ path &&= Pathname(path)
30
+ end
31
+ end
32
+
33
+ def source_file
34
+ File.new(source_file_pathname)
35
+ end
36
+
37
+ def source_data
38
+ all_lines.join("\n")
39
+ end
40
+
41
+ def all_lines
42
+ if @all_lines == nil
43
+ @all_lines = self.source.split("\n")[1..-1]
44
+ end
45
+ @all_lines
46
+ end
47
+
48
+ def cleaned_gcov_data
49
+ source_data
50
+ end
51
+
52
+ def raw_data
53
+ self.source
54
+ end
55
+
56
+ def line_number_in_line(line)
57
+ line =~ /^(\s*)(\d*)\|(\s*)(\d+)\|/
58
+ if $4 != nil
59
+ match = $4.strip
60
+ case match
61
+ when /[0-9]+/
62
+ return match.to_i
63
+ end
64
+ end
65
+ 0
66
+ end
67
+
68
+ def line_coverage_data
69
+ self.source.split("\n")[1..-1].map do |line|
70
+ coverage_for_line(line)
71
+ end
72
+ end
73
+
74
+ def coverage_for_line(line)
75
+ line = line.gsub(":", "|")
76
+ line =~ /^(\s*)(\d*)\|/
77
+
78
+ if $2 == nil
79
+ return nil
80
+ end
81
+
82
+ match = $2.strip
83
+ case match
84
+ when /[0-9]+/
85
+ match.to_i
86
+ when /#+/
87
+ 0
88
+ when "-"
89
+ nil
90
+ end
91
+ end
92
+
93
+ def branch_coverage_data
94
+ @branch_coverage_data ||= begin
95
+ Hash.new
96
+ end
97
+ end
98
+
99
+ def source_file_basename
100
+ File.basename(source_file_pathname, '.swift')
101
+ end
102
+
103
+ def line_number_separator
104
+ "|"
105
+ end
106
+
107
+ def supported_file_extensions
108
+ ["swift"]
109
+ end
110
+ private :supported_file_extensions
111
+
112
+ def ignored?
113
+ ignore = false
114
+ platform_ignore_list.map do |ignore_suffix|
115
+ ignore = source_file_pathname.to_s.end_with? ignore_suffix
116
+ if ignore
117
+ break
118
+ end
119
+ end
120
+ ignore ? ignore : super
121
+ end
122
+
123
+ def platform_ignore_list
124
+ ["MacOSX.platform/Developer/Library/Frameworks/XCTest.framework/Headers/XCTestAssertionsImpl.h",
125
+ "MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/objc/objc.h",
126
+ "MacOSX.platform/Developer/Library/Frameworks/XCTest.framework/Headers/XCTestAssertions.h"]
127
+ end
128
+ private :platform_ignore_list
129
+ end
130
+ end
@@ -2,14 +2,45 @@ require 'fileutils'
2
2
  require 'xcodeproj'
3
3
  require 'json'
4
4
  require 'yaml'
5
+ require 'shellwords'
5
6
 
6
7
  module Xcodeproj
8
+
7
9
  class Project
8
10
 
9
- def slather_setup_for_coverage
11
+ def slather_setup_for_coverage(format = :auto)
12
+ unless [:gcov, :clang, :auto].include?(format)
13
+ raise StandardError, "Only supported formats for setup are gcov, clang or auto"
14
+ end
15
+ if format == :auto
16
+ format = Slather.xcode_version[0] < 7 ? :gcov : :clang
17
+ end
18
+
10
19
  build_configurations.each do |build_configuration|
11
- build_configuration.build_settings["GCC_INSTRUMENT_PROGRAM_FLOW_ARCS"] = "YES"
12
- build_configuration.build_settings["GCC_GENERATE_TEST_COVERAGE_FILES"] = "YES"
20
+ if format == :clang
21
+ build_configuration.build_settings["CLANG_ENABLE_CODE_COVERAGE"] = "YES"
22
+ else
23
+ build_configuration.build_settings["GCC_INSTRUMENT_PROGRAM_FLOW_ARCS"] = "YES"
24
+ build_configuration.build_settings["GCC_GENERATE_TEST_COVERAGE_FILES"] = "YES"
25
+ end
26
+ end
27
+
28
+ # Patch xcschemes too
29
+ if format == :clang
30
+ if Gem::Requirement.new('~> 0.27') =~ Gem::Version.new(Xcodeproj::VERSION)
31
+ # @todo This will require to bump the xcodeproj dependency to ~> 0.27
32
+ # (which would require to bump cocoapods too)
33
+ schemes_path = Xcodeproj::XCScheme.shared_data_dir(self.path)
34
+ Xcodeproj::Project.schemes(self.path).each do |scheme_name|
35
+ xcscheme_path = "#{schemes_path + scheme_name}.xcscheme"
36
+ xcscheme = Xcodeproj::XCScheme.new(xcscheme_path)
37
+ xcscheme.test_action.xml_element.attributes['codeCoverageEnabled'] = 'YES'
38
+ xcscheme.save_as(self.path, scheme_name)
39
+ end
40
+ else
41
+ # @todo In the meantime, simply inform the user to do it manually
42
+ puts %Q(Ensure you enabled "Gather coverage data" in each of your scheme's Test action)
43
+ end
13
44
  end
14
45
  end
15
46
 
@@ -19,27 +50,32 @@ end
19
50
  module Slather
20
51
  class Project < Xcodeproj::Project
21
52
 
22
- attr_accessor :build_directory, :ignore_list, :ci_service, :coverage_service, :coverage_access_token, :source_directory, :output_directory, :xcodeproj, :show_html
53
+ attr_accessor :build_directory, :ignore_list, :ci_service, :coverage_service, :coverage_access_token, :source_directory,
54
+ :output_directory, :xcodeproj, :show_html, :verbose_mode, :input_format, :scheme, :binary_file, :binary_basename
23
55
 
24
56
  alias_method :setup_for_coverage, :slather_setup_for_coverage
25
57
 
26
58
  def self.open(xcodeproj)
27
59
  proj = super
28
- proj.configure_from_yml
29
60
  proj.xcodeproj = xcodeproj
30
61
  proj
31
62
  end
32
63
 
33
- def derived_data_dir
64
+ def derived_data_path
34
65
  File.expand_path('~') + "/Library/Developer/Xcode/DerivedData/"
35
66
  end
36
- private :derived_data_dir
67
+ private :derived_data_path
37
68
 
38
- def build_directory
39
- @build_directory || derived_data_dir
69
+ def coverage_files
70
+ if self.input_format == "profdata"
71
+ profdata_coverage_files
72
+ else
73
+ gcov_coverage_files
74
+ end
40
75
  end
76
+ private :coverage_files
41
77
 
42
- def coverage_files
78
+ def gcov_coverage_files
43
79
  coverage_files = Dir["#{build_directory}/**/*.gcno"].map do |file|
44
80
  coverage_file = coverage_file_class.new(self, file)
45
81
  # If there's no source file for this gcno, it probably belongs to another project.
@@ -52,7 +88,79 @@ module Slather
52
88
  dedupe(coverage_files)
53
89
  end
54
90
  end
55
- private :coverage_files
91
+ private :gcov_coverage_files
92
+
93
+ def profdata_coverage_files
94
+ files = profdata_llvm_cov_output.split("\n\n")
95
+
96
+ files.map do |source|
97
+ coverage_file = coverage_file_class.new(self, source)
98
+ !coverage_file.ignored? ? coverage_file : nil
99
+ end.compact
100
+ end
101
+ private :profdata_coverage_files
102
+
103
+ def profdata_coverage_dir
104
+ raise StandardError, "The specified build directory (#{self.build_directory}) does not exist" unless File.exists?(self.build_directory)
105
+ dir = nil
106
+ if self.scheme
107
+ dir = Dir["#{build_directory}/**/CodeCoverage/#{self.scheme}"].first
108
+ else
109
+ dir = Dir["#{build_directory}/**/#{self.products.first.name}"].first
110
+ end
111
+
112
+ raise StandardError, "No coverage directory found. Are you sure your project is setup for generating coverage files? Try `slather setup your/project.xcodeproj`" unless dir != nil
113
+ dir
114
+ end
115
+
116
+ def profdata_file
117
+ profdata_coverage_dir = self.profdata_coverage_dir
118
+ if profdata_coverage_dir == nil
119
+ raise StandardError, "No coverage directory found. Please make sure the \"Code Coverage\" checkbox is enabled in your scheme's Test action or the build_directory property is set."
120
+ end
121
+
122
+ file = Dir["#{profdata_coverage_dir}/**/Coverage.profdata"].first
123
+ unless file != nil
124
+ return nil
125
+ end
126
+ return File.expand_path(file)
127
+ end
128
+ private :profdata_file
129
+
130
+ def find_binary_file_for_app(app_bundle_file)
131
+ app_bundle_file_name_noext = Pathname.new(app_bundle_file).basename.to_s.gsub(".app", "")
132
+ Dir["#{app_bundle_file}/**/#{app_bundle_file_name_noext}"].first
133
+ end
134
+
135
+ def find_binary_file_for_dynamic_lib(framework_bundle_file)
136
+ framework_bundle_file_name_noext = Pathname.new(framework_bundle_file).basename.to_s.gsub(".framework", "")
137
+ "#{framework_bundle_file}/#{framework_bundle_file_name_noext}"
138
+ end
139
+
140
+ def find_binary_file_for_static_lib(xctest_bundle_file)
141
+ xctest_bundle_file_name_noext = Pathname.new(xctest_bundle_file).basename.to_s.gsub(".xctest", "")
142
+ Dir["#{xctest_bundle_file}/**/#{xctest_bundle_file_name_noext}"].first
143
+ end
144
+
145
+ def unsafe_profdata_llvm_cov_output
146
+ profdata_file_arg = profdata_file
147
+ if profdata_file_arg == nil
148
+ raise StandardError, "No Coverage.profdata files found. Please make sure the \"Code Coverage\" checkbox is enabled in your scheme's Test action or the build_directory property is set."
149
+ end
150
+
151
+ if self.binary_file == nil
152
+ raise StandardError, "No binary file found."
153
+ end
154
+
155
+ llvm_cov_args = %W(show -instr-profile #{profdata_file_arg} #{self.binary_file})
156
+ `xcrun llvm-cov #{llvm_cov_args.shelljoin}`
157
+ end
158
+ private :unsafe_profdata_llvm_cov_output
159
+
160
+ def profdata_llvm_cov_output
161
+ unsafe_profdata_llvm_cov_output.encode!('UTF-8', 'binary', :invalid => :replace, undef: :replace)
162
+ end
163
+ private :profdata_llvm_cov_output
56
164
 
57
165
  def dedupe(coverage_files)
58
166
  coverage_files.group_by(&:source_file_pathname).values.map { |cf_array| cf_array.max_by(&:percentage_lines_tested) }
@@ -67,45 +175,73 @@ module Slather
67
175
  @yml ||= File.exist?(yml_filename) ? YAML.load_file(yml_filename) : {}
68
176
  end
69
177
 
70
- def configure_from_yml
71
- configure_build_directory_from_yml
72
- configure_ignore_list_from_yml
73
- configure_ci_service_from_yml
74
- configure_coverage_access_token_from_yml
75
- configure_coverage_service_from_yml
76
- configure_source_directory_from_yml
77
- configure_output_directory_from_yml
178
+ def configure
179
+ configure_build_directory
180
+ configure_ignore_list
181
+ configure_ci_service
182
+ configure_coverage_access_token
183
+ configure_coverage_service
184
+ configure_source_directory
185
+ configure_output_directory
186
+ configure_input_format
187
+ configure_scheme
188
+ configure_binary_file
189
+
190
+ if self.verbose_mode
191
+ puts "\nProcessing coverage file: #{profdata_file}"
192
+ puts "Against binary file: #{self.binary_file}\n\n"
193
+ end
78
194
  end
79
195
 
80
- def configure_build_directory_from_yml
81
- self.build_directory = self.class.yml["build_directory"] if self.class.yml["build_directory"] && !@build_directory
196
+ def configure_build_directory
197
+ self.build_directory ||= self.class.yml["build_directory"] || derived_data_path
82
198
  end
83
199
 
84
- def configure_source_directory_from_yml
200
+ def configure_source_directory
85
201
  self.source_directory ||= self.class.yml["source_directory"] if self.class.yml["source_directory"]
86
202
  end
87
203
 
88
- def configure_output_directory_from_yml
204
+ def configure_output_directory
89
205
  self.output_directory ||= self.class.yml["output_directory"] if self.class.yml["output_directory"]
90
206
  end
91
207
 
92
- def configure_ignore_list_from_yml
208
+ def configure_ignore_list
93
209
  self.ignore_list ||= [(self.class.yml["ignore"] || [])].flatten
94
210
  end
95
211
 
96
- def configure_ci_service_from_yml
212
+ def configure_ci_service
97
213
  self.ci_service ||= (self.class.yml["ci_service"] || :travis_ci)
98
214
  end
99
215
 
216
+ def configure_input_format
217
+ self.input_format ||= self.class.yml["input_format"] || input_format
218
+ end
219
+
220
+ def input_format=(format)
221
+ format ||= "auto"
222
+ unless %w(gcov profdata auto).include?(format)
223
+ raise StandardError, "Only supported input formats are gcov, profdata or auto"
224
+ end
225
+ if format == "auto"
226
+ @input_format = Slather.xcode_version[0] < 7 ? "gcov" : "profdata"
227
+ else
228
+ @input_format = format
229
+ end
230
+ end
231
+
232
+ def configure_scheme
233
+ self.scheme ||= self.class.yml["scheme"] if self.class.yml["scheme"]
234
+ end
235
+
100
236
  def ci_service=(service)
101
237
  @ci_service = service && service.to_sym
102
238
  end
103
239
 
104
- def configure_coverage_service_from_yml
240
+ def configure_coverage_service
105
241
  self.coverage_service ||= (self.class.yml["coverage_service"] || :terminal)
106
242
  end
107
243
 
108
- def configure_coverage_access_token_from_yml
244
+ def configure_coverage_access_token
109
245
  self.coverage_access_token ||= (ENV["COVERAGE_ACCESS_TOKEN"] || self.class.yml["coverage_access_token"] || "")
110
246
  end
111
247
 
@@ -128,5 +264,33 @@ module Slather
128
264
  end
129
265
  @coverage_service = service
130
266
  end
267
+
268
+ def configure_binary_file
269
+ if self.input_format == "profdata"
270
+ self.binary_file ||= self.class.yml["binary_file"] || File.expand_path(find_binary_file)
271
+ end
272
+ end
273
+
274
+ def find_binary_file
275
+ xctest_bundle = Dir["#{profdata_coverage_dir}/**/*.xctest"].reject { |bundle|
276
+ bundle.include? "-Runner.app/PlugIns/"
277
+ }.first
278
+ raise StandardError, "No product binary found in #{profdata_coverage_dir}. Are you sure your project is setup for generating coverage files? Try `slather setup your/project.xcodeproj`" unless xctest_bundle != nil
279
+
280
+ # Find the matching binary file
281
+ search_for = self.binary_basename || self.class.yml["binary_basename"] || '*'
282
+ xctest_bundle_file_directory = Pathname.new(xctest_bundle).dirname
283
+ app_bundle = Dir["#{xctest_bundle_file_directory}/#{search_for}.app"].first
284
+ dynamic_lib_bundle = Dir["#{xctest_bundle_file_directory}/#{search_for}.framework"].first
285
+
286
+ if app_bundle != nil
287
+ find_binary_file_for_app(app_bundle)
288
+ elsif dynamic_lib_bundle != nil
289
+ find_binary_file_for_dynamic_lib(dynamic_lib_bundle)
290
+ else
291
+ find_binary_file_for_static_lib(xctest_bundle)
292
+ end
293
+ end
294
+
131
295
  end
132
296
  end
@@ -1,3 +1,3 @@
1
1
  module Slather
2
- VERSION = "1.8.3"
2
+ VERSION = "2.0.0"
3
3
  end
data/lib/slather.rb CHANGED
@@ -1,7 +1,9 @@
1
1
  require 'slather/version'
2
2
  require 'slather/project'
3
+ require 'slather/coverage_info'
3
4
  require 'slather/coverage_file'
4
- require 'slather/coveralls_coverage_file'
5
+ require 'slather/coveralls_coverage'
6
+ require 'slather/profdata_coverage_file'
5
7
  require 'slather/coverage_service/cobertura_xml_output'
6
8
  require 'slather/coverage_service/coveralls'
7
9
  require 'slather/coverage_service/hardcover'
@@ -17,4 +19,10 @@ module Slather
17
19
  Pod::UI.warn("[Slather] prepare_pods is now deprecated. The call to prepare_pods in your Podfile can simply be ommitted.")
18
20
  end
19
21
 
22
+ def self.xcode_version
23
+ xcode_path = `xcode-select -p`.strip
24
+ xcode_version = `mdls -name kMDItemVersion -raw #{xcode_path.shellescape}/../..`.strip
25
+ xcode_version.split('.').map(&:to_i)
26
+ end
27
+
20
28
  end
data/slather.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["Mark Larsen"]
10
10
  spec.email = ["mark@venmo.com"]
11
11
  spec.summary = %q{Test coverage reports for Xcode projects}
12
- spec.homepage = "https://github.com/venmo/slather"
12
+ spec.homepage = "https://github.com/SlatherOrg/slather"
13
13
  spec.license = "MIT"
14
14
 
15
15
  spec.files = `git ls-files -z`.split("\x0")
@@ -20,13 +20,13 @@ Gem::Specification.new do |spec|
20
20
  spec.add_development_dependency "bundler", "~> 1.6"
21
21
  spec.add_development_dependency "coveralls"
22
22
  spec.add_development_dependency "rake", "~> 10.3"
23
- spec.add_development_dependency "rspec", "~> 2.14"
23
+ spec.add_development_dependency "rspec", "~> 3.3"
24
24
  spec.add_development_dependency "pry", "~> 0.9"
25
- spec.add_development_dependency "cocoapods", "~> 0.39.0"
25
+ spec.add_development_dependency "cocoapods", ">= 0.39.0", "< 1.1.0"
26
26
  spec.add_development_dependency "json_spec", "~> 1.1.4"
27
27
  spec.add_development_dependency "equivalent-xml", "~> 0.5.1"
28
28
 
29
29
  spec.add_dependency "clamp", "~> 0.6"
30
- spec.add_dependency "xcodeproj", "~> 0.28.0"
30
+ spec.add_dependency "xcodeproj", ">= 0.28.2", "< 1.1.0"
31
31
  spec.add_dependency "nokogiri", "~> 1.6.3"
32
32
  end