alcove 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +22 -0
- data/README.md +26 -0
- data/bin/alcove +68 -0
- data/lib/alcove.rb +113 -0
- data/lib/alcove/version.rb +3 -0
- metadata +91 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c3a24347defb0bd648d7c15cd13d754590615977
|
4
|
+
data.tar.gz: a7530953e48cfc71bde431f94a235b3a17407293
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e74cccadf0a4dcd053843c3d5271c27e11c1823d91499d855c86981ea76b9c90c55490fd358522866b5c8c39ba54ca3a0f9542ee9827d71234e3be664da9f1a6
|
7
|
+
data.tar.gz: a95b48ef3a9ccd19fabda7e85c88fb3f47c2a2602bf34b5483ca6bef751b9859f9d7e36060a826bbe6bca5d3d9ea045bc0382845ac72f3664566c2c8869106c8
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Isaac Overacker
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
22
|
+
|
data/README.md
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# Alcove [![Build Status](https://travis-ci.org/ioveracker/Alcove.svg?branch=master)](https://travis-ci.org/ioveracker/Alcove)
|
2
|
+
Painless code coverage reporting for Objective-C projects. Most of the heavy lifting is done by the venerable lcov. Alcove simply searches the nooks and crannies to collect the data needed to generate the report and ties everything together for you. Best of all, it's a gem with minimal depedencies, so installation is quick and painless.
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
|
6
|
+
$ sudo gem install alcove
|
7
|
+
|
8
|
+
If you don't have it already, you'll also need to install lcov.
|
9
|
+
|
10
|
+
*Homebrew*
|
11
|
+
|
12
|
+
$ brew install lcov
|
13
|
+
|
14
|
+
*MacPorts*
|
15
|
+
|
16
|
+
$ sudo port install lcov
|
17
|
+
|
18
|
+
## Xcode Project Configuration
|
19
|
+
If you haven't already, open your project in Xcode and update your main target to Generate Test Coverage Files and Instrument Program Flow *for Debug configuration only*).
|
20
|
+
|
21
|
+
## Generating Reports
|
22
|
+
Now that you have the prerequisites out of the way, you can generate a report. Make sure you've recently executed your tests, then:
|
23
|
+
|
24
|
+
alcove --product-name <your-product-name>
|
25
|
+
|
26
|
+
Be sure to check out the --help for additional options for fine-tuning your report.
|
data/bin/alcove
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
3
|
+
require 'alcove'
|
4
|
+
require 'alcove/version'
|
5
|
+
require 'ostruct'
|
6
|
+
require 'optparse'
|
7
|
+
|
8
|
+
options = OpenStruct.new
|
9
|
+
OptionParser.new do |opts|
|
10
|
+
opts.banner = "Usage: alcove --product-name <product-name> [options]"
|
11
|
+
|
12
|
+
opts.on('-h', '--help', 'Displays the help screen') do
|
13
|
+
puts opts
|
14
|
+
exit
|
15
|
+
end
|
16
|
+
|
17
|
+
options.output_directory = 'alcove-report'
|
18
|
+
opts.on('-o', '--output-directory DIR', 'Place report in DIR instead of default') do |o|
|
19
|
+
options.output_directory = o
|
20
|
+
end
|
21
|
+
|
22
|
+
options.product_name = ''
|
23
|
+
opts.on('-p', '--product-name NAME', 'The name of your product') do |p|
|
24
|
+
options.product_name = p
|
25
|
+
end
|
26
|
+
|
27
|
+
options.remove_filter = []
|
28
|
+
opts.on('-r', '--remove-filter X,Y,Z...', ::Array, 'A list of filters (e.g. *.h,main.m)') do |r|
|
29
|
+
options.remove_filter = r
|
30
|
+
end
|
31
|
+
|
32
|
+
opts.on('-s', '--search-directory DIR', 'Search in DIR for coverage files') do |s|
|
33
|
+
options.search_directory = s
|
34
|
+
end
|
35
|
+
|
36
|
+
options.verbose = false
|
37
|
+
opts.on('-v', '--verbose', 'Output additional information') do
|
38
|
+
options.verbose = true
|
39
|
+
end
|
40
|
+
|
41
|
+
opts.on_tail('--version', 'Show version') do
|
42
|
+
puts Alcove::VERSION
|
43
|
+
exit
|
44
|
+
end
|
45
|
+
|
46
|
+
begin
|
47
|
+
opts.parse!(ARGV)
|
48
|
+
if options.product_name.length == 0
|
49
|
+
puts '--product-name is required'.yellow
|
50
|
+
puts opts
|
51
|
+
exit(1)
|
52
|
+
end
|
53
|
+
rescue OptionParser::InvalidOption => e
|
54
|
+
puts e
|
55
|
+
puts opts
|
56
|
+
exit(1)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
alcoveOptions = OpenStruct.new
|
61
|
+
alcoveOptions.output_directory = options.output_directory
|
62
|
+
alcoveOptions.product_name = options.product_name
|
63
|
+
alcoveOptions.remove_filter = options.remove_filter
|
64
|
+
alcoveOptions.search_directory = options.search_directory
|
65
|
+
alcoveOptions.verbose = options.verbose
|
66
|
+
|
67
|
+
alcove = Alcove.new(alcoveOptions)
|
68
|
+
alcove.generate_report
|
data/lib/alcove.rb
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'colored'
|
2
|
+
require 'etc'
|
3
|
+
require 'find'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'ostruct'
|
6
|
+
require 'optparse'
|
7
|
+
|
8
|
+
class Alcove
|
9
|
+
def initialize(options)
|
10
|
+
@output_directory = options.output_directory
|
11
|
+
@product_name = options.product_name
|
12
|
+
@remove_filter = options.remove_filter
|
13
|
+
@verbose = options.verbose
|
14
|
+
@search_directory = options.search_directory
|
15
|
+
end
|
16
|
+
|
17
|
+
def generate_report
|
18
|
+
temp_dir = 'alcove-temp'
|
19
|
+
# geninfo parameters
|
20
|
+
gi_filename = 'alcove-info.temp'
|
21
|
+
gi_filename_absolute = File.join(temp_dir, gi_filename)
|
22
|
+
# lcov parameters
|
23
|
+
lcov_filename = 'alcove-lcov.info'
|
24
|
+
lcov_filename_absolute = File.join(temp_dir, lcov_filename)
|
25
|
+
lcov_system_removals = ['*iPhoneSimulator*']
|
26
|
+
|
27
|
+
puts ' 🔍 Generating report...'
|
28
|
+
|
29
|
+
FileUtils.rm_rf(temp_dir)
|
30
|
+
FileUtils.mkdir(temp_dir)
|
31
|
+
|
32
|
+
puts ' 📦 Gathering .gcno and .gcda files...' if @verbose
|
33
|
+
copy_input_files(@product_name, temp_dir)
|
34
|
+
|
35
|
+
gen_success = gen_info_files(gi_filename_absolute, temp_dir)
|
36
|
+
if gen_success
|
37
|
+
puts ' ✅ geninfo successful'.green if @verbose
|
38
|
+
else
|
39
|
+
puts ' 🚫 geninfo failed!'.red
|
40
|
+
FileUtils.rm_rf(temp_dir)
|
41
|
+
exit(1)
|
42
|
+
end
|
43
|
+
|
44
|
+
lcov_removals = lcov_system_removals + @remove_filter
|
45
|
+
lcov_success = lcov(gi_filename_absolute, lcov_removals, lcov_filename_absolute)
|
46
|
+
if lcov_success
|
47
|
+
puts ' ✅ lcov successful'.green if @verbose
|
48
|
+
else
|
49
|
+
puts ' 🚫 lcov failed!'.red
|
50
|
+
FileUtils.rm_rf(temp_dir)
|
51
|
+
exit(1)
|
52
|
+
end
|
53
|
+
|
54
|
+
genhtml_success = genhtml(@output_directory, lcov_filename_absolute)
|
55
|
+
if genhtml_success
|
56
|
+
puts '' if @verbose
|
57
|
+
puts ' ✅ Successfully generated report'.green
|
58
|
+
puts " 🍻 Open #{@output_directory}/index.html to view the report"
|
59
|
+
else
|
60
|
+
puts ' 🚫 genhtml failed!'.red
|
61
|
+
FileUtils.rm_rf(temp_dir)
|
62
|
+
exit(1)
|
63
|
+
end
|
64
|
+
|
65
|
+
FileUtils.rm_rf(temp_dir)
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def copy_input_files(product_name, temp_dir)
|
71
|
+
derived_data = ''
|
72
|
+
if @search_directory
|
73
|
+
puts " Search directory provided." if @verbose
|
74
|
+
derived_data = @search_directory
|
75
|
+
elsif ENV['XCS_SOURCE_DIR']
|
76
|
+
puts " Xcode Server found." if @verbose
|
77
|
+
derived_data = ENV['XCS_SOURCE_DIR'].sub('Source', 'DerivedData')
|
78
|
+
else
|
79
|
+
puts " Development machine found." if @verbose
|
80
|
+
derived_data = File.join(Etc.getpwuid.dir, "/Library/Developer/Xcode/DerivedData")
|
81
|
+
end
|
82
|
+
|
83
|
+
puts " Searching in #{derived_data}..." if @verbose
|
84
|
+
Find.find(derived_data) do |path|
|
85
|
+
if path.match(/#{product_name}.*\.gcda\Z/) || path.match(/#{product_name}.*\.gcno\Z/)
|
86
|
+
puts " 👍 .#{path.sub(derived_data, "")}".green if @verbose
|
87
|
+
FileUtils.cp(path, "#{temp_dir}/")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def gen_info_files(filename, temp_dir)
|
93
|
+
absolute_temp_dir = File.join(Dir.pwd, temp_dir)
|
94
|
+
gen_info_cmd = "geninfo #{absolute_temp_dir}/*.gcno --output-filename #{filename}"
|
95
|
+
gen_info_cmd += ' --quiet' unless @verbose
|
96
|
+
return system gen_info_cmd
|
97
|
+
end
|
98
|
+
|
99
|
+
def lcov(info_filename, filenames_to_remove, lcov_file)
|
100
|
+
all_removals = filenames_to_remove.map { |i| '"' + i.to_s + '"' }.join(" ")
|
101
|
+
lcov_cmd = "lcov --remove #{info_filename} #{all_removals} > #{lcov_file}"
|
102
|
+
lcov_cmd += ' --quiet' unless @verbose
|
103
|
+
return system lcov_cmd
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
def genhtml(output_directory, lcov_filename)
|
108
|
+
FileUtils.mkpath(output_directory)
|
109
|
+
genhtml_cmd = "genhtml --no-function-coverage --no-branch-coverage --output-directory #{output_directory} #{lcov_filename}"
|
110
|
+
genhtml_cmd += ' --quiet' unless @verbose
|
111
|
+
return system genhtml_cmd
|
112
|
+
end
|
113
|
+
end
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: alcove
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Isaac Overacker
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-02-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: colored
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Painless code coverage reporting for Xcode projects written in Objective-C.
|
56
|
+
email: isaac@overacker.me
|
57
|
+
executables:
|
58
|
+
- alcove
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- lib/alcove/version.rb
|
63
|
+
- lib/alcove.rb
|
64
|
+
- bin/alcove
|
65
|
+
- README.md
|
66
|
+
- LICENSE
|
67
|
+
homepage: https://github.com/ioveracker/alcove
|
68
|
+
licenses:
|
69
|
+
- MIT
|
70
|
+
metadata: {}
|
71
|
+
post_install_message:
|
72
|
+
rdoc_options: []
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - '>='
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
requirements: []
|
86
|
+
rubyforge_project:
|
87
|
+
rubygems_version: 2.0.14
|
88
|
+
signing_key:
|
89
|
+
specification_version: 4
|
90
|
+
summary: Painless code coverage reporting for Objective-C.
|
91
|
+
test_files: []
|