xctracker 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 994a2e1eb3435c742887b81ae76cfdf07f5b19c3
4
+ data.tar.gz: 888eb3e06baafa50a5f5317b871a42bb1d4a7ad1
5
+ SHA512:
6
+ metadata.gz: b26df86de6a6c77d8689fd8913d469b8d5abf159bc99a10d5211a689e100f5821d60e9f8ed8c9465db379b9a73202fce1b4b62cdf08d835e45b59fc641eecc81
7
+ data.tar.gz: 1dbc8e8a1be9a3719934bb547579447c5ea8ef265240bbfe952ef1c193a3586c072c10fcf9f026cc83efcff455d9f7ed7ddb2b75376d24c22a0d037ffce00f91
data/.coveralls.yml ADDED
@@ -0,0 +1 @@
1
+ repo_token: 1pEOUTj3O1iV7D3cX8vNSEqgMoowKRKwW
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,17 @@
1
+ language: ruby
2
+ cache: bundler
3
+ script:
4
+ - "bundle exec rspec spec"
5
+ rvm:
6
+ # OS X 10.9.5-10.10.0 (2.0.0-p481)
7
+ - 2.0.0-p481
8
+ # OS X 10.9.3-10.9.4
9
+ - 2.0.0-p451
10
+ - 2.3.1
11
+ matrix:
12
+ include:
13
+ - rvm: system
14
+ osx_image: xcode8.1
15
+ language: objective-c
16
+ before_install: sudo gem install bundler
17
+ - rvm: 2.3.1
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2016 Kohki Miki
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.
data/README.md ADDED
@@ -0,0 +1,103 @@
1
+ # xctracker
2
+
3
+ [![Build Status](https://travis-ci.org/giginet/xctracker.svg?branch=master)](https://travis-ci.org/giginet/xctracker)
4
+ [![Coverage Status](https://coveralls.io/repos/github/giginet/xctracker/badge.svg?branch=master)](https://coveralls.io/github/giginet/xctracker?branch=master)
5
+
6
+ Command line interface to analyze build times of Swift projects
7
+
8
+ ![](https://raw.githubusercontent.com/giginet/xctracker/master/assets/sample_output.png)
9
+
10
+ This tool developed in working time for Cookpad.
11
+
12
+ ## Installation
13
+
14
+ ```
15
+ gem install xctracker
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ - 1 Add `-Xfrontend -debug-time-function-bodies` build flags on your Xcode project.
21
+
22
+ ![](https://raw.githubusercontent.com/giginet/xctracker/master/assets/build_flags.png)
23
+
24
+ - 2 Build your project
25
+ - 3 Execute `xctracker`
26
+
27
+ ```
28
+ $ xctracker [PRODUCT_NAME or ACTIVITY_LOG_PATH] [options]
29
+ ```
30
+
31
+ `xctracker` searches the latest build log on your DerivedData directory.
32
+
33
+ You can also specify the `.xcactivitylog`.
34
+
35
+ ```
36
+ $ xctracker MyApp
37
+ $ xctracker ~/Library/Developer/Xcode/DerivedData/MyApp-xxxxxxxxxxx/Logs/Build/0761C73D-3B6C-449A-BE89-6D11DAB748FE.xcactivitylog
38
+ ```
39
+
40
+ Sample output is here
41
+
42
+ ```
43
+ +--------------------------------------------------+------+------------------------------------------------------------------------------------------------------------------------------------------+----------+
44
+ | File | Line | Method name | Time(ms) |
45
+ +--------------------------------------------------+------+------------------------------------------------------------------------------------------------------------------------------------------+----------+
46
+ | Phakchi/Sources/Phakchi/Interaction.swift | 17 | get {} | 69.9 |
47
+ | Phakchi/Sources/Phakchi/Matcher.swift | 7 | get {} | 68.9 |
48
+ | Phakchi/Sources/Phakchi/InteractionBuilder.swift | 87 | func clean() | 49.8 |
49
+ | Phakchi/Sources/Phakchi/Session.swift | 74 | public func run(completionBlock: TestCompletionBlock? = default, executionBlock: @escaping TestExecutionBlock) | 49.6 |
50
+ | Phakchi/Sources/Phakchi/Session.swift | 65 | @discardableResult public func willRespondWith(status: Int, headers: Headers? = default, body: Body? = default) -> Self | 28.3 |
51
+ | Phakchi/Sources/Phakchi/ControlServer.swift | 20 | public func startSession(consumerName: String, providerName: String, completion completionBlock: StartSessionCompletionBlock? = default) | 24.6 |
52
+ | Phakchi/Sources/Phakchi/ControlServer.swift | 24 | (closure) | 23.9 |
53
+ | Phakchi/Sources/Phakchi/InteractionBuilder.swift | 19 | private func makeHeaders(_ headers: Headers?, defaultHeaders: Headers?) -> Headers? | 21.5 |
54
+ | Phakchi/Sources/Phakchi/ServiceClient.swift | 47 | func registerInteraction(_ interaction: Interaction, completionHandler: CompletionHandler? = default) | 16.4 |
55
+ | Phakchi/Sources/Phakchi/ServiceClient.swift | 60 | func verify(_ completionHandler: VerificationCompletionHandler? = default) | 14.3 |
56
+ | Phakchi/Sources/Phakchi/ServiceClient.swift | 27 | func resumeSessionTask(_ request: URLRequest, completionHandler: CompletionHandler? = default) | 13.3 |
57
+ | Phakchi/Sources/Phakchi/ControlServer.swift | 32 | public func session(forConsumerName consumerName: String, providerName: String) -> Session? | 9.7 |
58
+ | Phakchi/Sources/Phakchi/InteractionBuilder.swift | 94 | get {} | 5.9 |
59
+ | Phakchi/Sources/Phakchi/ServiceClient.swift | 15 | func makePactRequest(to endpoint: String, method: HTTPMethod, headers: [String : String] = default) -> URLRequest | 5.3 |
60
+ | Phakchi/Sources/Phakchi/ServiceClient.swift | 51 | func registerInteractions(_ interactions: [Interaction], completionHandler: CompletionHandler? = default) | 5.1 |
61
+ | Phakchi/Sources/Phakchi/Encodable.swift | 39 | get {} | 4.8 |
62
+ | Phakchi/Sources/Phakchi/ServiceClient.swift | 121 | func start(session consumerName: String, providerName: String, completionHandler: @escaping CreateSessionCompletionHandler) | 3.7 |
63
+ | Phakchi/Sources/Phakchi/Encodable.swift | 29 | get {} | 3.4 |
64
+ | Phakchi/Sources/Phakchi/ServiceClient.swift | 72 | func writePact(for providerName: String, consumerName: String, exportPath: URL?, completionHandler: CompletionHandler? = default) | 3.3 |
65
+ | Phakchi/Sources/Phakchi/ServiceClient.swift | 125 | (closure) | 3.1 |
66
+ +-------------------------------------------------------------------------------------------+------+------------------------------------------------------------------------------------------------------------------------------------------+----------+
67
+ ```
68
+
69
+ ### Available Options
70
+
71
+ |option|shorthand|description|
72
+ |------|---------|-----------|
73
+ |--limit|-l|Limit for display|
74
+ |--show-invalids||Show invalid location results|
75
+ |--order|-o|Sort order (default,time,file)|
76
+
77
+ ## Use custom reporters
78
+
79
+ You can use reporters to output tracking logs.
80
+
81
+ ```ruby
82
+ require 'xctracker'
83
+
84
+ tracker = Xctracker::Tracker.by_product_name('MyApp')
85
+ tracker.reporters = [
86
+ Xctracker::StandardOutputReporter.new(limit: 20, order: :time)],
87
+ Xctracker::JSONReporter.new({output_path: 'result.json'})
88
+ ]
89
+ tracker.report!
90
+ ```
91
+
92
+ You can also implement your own reporters.
93
+
94
+ See implementation of built-in reporters for detail.
95
+
96
+ ## License
97
+
98
+ MIT License
99
+
100
+ ## Contributing
101
+
102
+ Bug reports and pull requests are welcome on GitHub at https://github.com/giginet/xctracker.
103
+
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
Binary file
Binary file
data/bin/xctracker ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.push File.expand_path("../../lib", __FILE__)
3
+
4
+ require 'xctracker'
5
+
6
+ Xctracker.execute(ARGV)
data/lib/xctracker.rb ADDED
@@ -0,0 +1,58 @@
1
+ require "xctracker/derived_data"
2
+ require "xctracker/exceptions"
3
+ require "xctracker/execution"
4
+ require "xctracker/tracker"
5
+ require "xctracker/version"
6
+ require "xctracker/reporters/abstract_reporter"
7
+ require "xctracker/reporters/standard_output_reporter"
8
+ require "xctracker/reporters/json_reporter"
9
+ require "colorize"
10
+ require "optparse"
11
+ require "ostruct"
12
+
13
+ module Xctracker
14
+ class << self
15
+ def execute(args)
16
+ options = OpenStruct.new
17
+ options.order = :time
18
+ options.reporters = [:standard_output]
19
+
20
+ parser = OptionParser.new do |opts|
21
+ opts.banner = "Usage: xctracker [product name or .xcactivitylog file] [options]".red
22
+
23
+ opts.on("--[no-]show-invalids", "Show invalid location results") { |v| options.show_invalid_locations = v }
24
+ opts.on("-o [ORDER]", [:default, :time, :file], "Sort order") { |v| options.order = v }
25
+ opts.on("-l", "--limit [LIMIT]", Integer, "Limit for display") { |v| options.limit = v }
26
+ opts.on_tail("-h", "--help", "Show this message") do
27
+ puts opts
28
+ exit
29
+ end
30
+ end
31
+ parser.parse!(args)
32
+
33
+ target = args.pop
34
+ unless target
35
+ puts parser
36
+ exit 1
37
+ end
38
+
39
+ order = options[:order] or :time
40
+
41
+ begin
42
+ if target.end_with?('.xcactivitylog')
43
+ tracker = Tracker.by_path(target)
44
+ else
45
+ tracker = Tracker.by_product_name(target)
46
+ end
47
+ tracker.reporters = [
48
+ StandardOutputReporter.new(limit: options[:limit],
49
+ order: order,
50
+ show_invalid_locations: options[:show_invalid_locations])
51
+ ]
52
+ tracker.report!
53
+ rescue Exception => e
54
+ puts e.message.red
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,67 @@
1
+ require 'zlib'
2
+
3
+ module Xctracker
4
+ class DerivedData
5
+ class << self
6
+ def all
7
+ pattern = File.join(derived_data_root, "**", "Logs", "Build", "*.xcactivitylog")
8
+ by_pattern(pattern)
9
+ end
10
+
11
+ def by_product_name(product_name)
12
+ pattern = File.join(derived_data_root, "#{product_name}-*", "Logs", "Build", "*.xcactivitylog")
13
+ by_pattern(pattern)
14
+ end
15
+
16
+ private
17
+
18
+ def by_pattern(pattern)
19
+ derived_data = Dir.glob(pattern).map { |path|
20
+ DerivedData.new(path)
21
+ }
22
+
23
+ if derived_data.empty?
24
+ raise DerivedDataNotFound, 'Any matching derived data are not found'
25
+ end
26
+
27
+ derived_data.max { |data| data.updated_at }
28
+ end
29
+
30
+ def derived_data_root
31
+ File.expand_path('~/Library/Developer/Xcode/DerivedData')
32
+ end
33
+ end
34
+
35
+ def initialize(path)
36
+ @path = path
37
+ end
38
+
39
+ def updated_at
40
+ File.mtime(@path)
41
+ end
42
+
43
+ def executions
44
+ @executions ||= lines.map { |line|
45
+ if line =~ /^\d*\.?\dms\t/
46
+ time, file, method_name = line.split(/\t/)
47
+ Execution.new(time, file, method_name)
48
+ end
49
+ }.compact
50
+ end
51
+
52
+ def flag_enabled?
53
+ lines.any? { |l| l.include?('-Xfrontend -debug-time-function-bodies') }
54
+ end
55
+
56
+ private
57
+
58
+ def lines
59
+ unless @lines
60
+ Zlib::GzipReader.open(@path) do |gz|
61
+ @lines = gz.read.split(/\r/)
62
+ end
63
+ end
64
+ @lines
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,10 @@
1
+ module Xctracker
2
+ class DerivedDataNotFound < Exception
3
+ end
4
+
5
+ class BuildFlagIsNotEnabled < Exception
6
+ end
7
+
8
+ class OutputPathIsNotSpecified < Exception
9
+ end
10
+ end
@@ -0,0 +1,62 @@
1
+ module Xctracker
2
+ class Execution
3
+ Struct.new('Position', :path, :line, :column)
4
+
5
+ attr_reader :time, :position, :method_name
6
+
7
+ def initialize(time, position, method_name)
8
+ @time = time.to_f
9
+ unless position =~ /<invalid loc>/
10
+ path, line, column = position.split(':')
11
+ @position = Struct::Position.new(path, line.to_i, column.to_i)
12
+ end
13
+ @method_name = method_name
14
+ end
15
+
16
+ def to_h
17
+ {
18
+ method_name: method_name,
19
+ time: time,
20
+ path: path,
21
+ line: line,
22
+ column: column
23
+ }
24
+ end
25
+
26
+ def invalid?
27
+ !position
28
+ end
29
+
30
+ def path
31
+ if @position
32
+ @position.path
33
+ else
34
+ nil
35
+ end
36
+ end
37
+
38
+ def filename
39
+ if path
40
+ File.basename(path)
41
+ else
42
+ nil
43
+ end
44
+ end
45
+
46
+ def column
47
+ if @position
48
+ @position.column
49
+ else
50
+ nil
51
+ end
52
+ end
53
+
54
+ def line
55
+ if @position
56
+ @position.line
57
+ else
58
+ nil
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,45 @@
1
+ module Xctracker
2
+ class AbstractReporter
3
+ attr_reader :options
4
+
5
+ def initialize(options = {})
6
+ @options = options
7
+ end
8
+
9
+ def report!(executions)
10
+ raise NotImplementedError, 'Not implemented'
11
+ end
12
+
13
+ protected
14
+
15
+ def filter_executions(executions)
16
+ executions = sort_executions(executions, order)
17
+ executions = executions.delete_if(&:invalid?) unless show_invalid_locations?
18
+ executions = executions[0...limit] if limit
19
+ executions
20
+ end
21
+
22
+ def sort_executions(executions, order)
23
+ case order
24
+ when :default
25
+ executions
26
+ when :time
27
+ executions.sort { |a, b| [b.time, (a.filename or ''), (a.line or 0)] <=> [a.time, (b.filename or ''), (b.line or 0)] }
28
+ when :file
29
+ executions.sort { |a, b| [(a.filename or ''), (a.line or 0)] <=> [(b.filename or ''), (b.line or 0)] }
30
+ end
31
+ end
32
+
33
+ def limit
34
+ options[:limit]
35
+ end
36
+
37
+ def show_invalid_locations?
38
+ options[:show_invalid_locations] || false
39
+ end
40
+
41
+ def order
42
+ options[:order] || :time
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,22 @@
1
+ require 'json'
2
+
3
+ module Xctracker
4
+ class JSONReporter < AbstractReporter
5
+ def report!(executions)
6
+ json = filter_executions(executions).map(&:to_h)
7
+ unless output_path
8
+ raise OutputPathIsNotSpecified, '[JSONReporter] output_path is not specified'
9
+ end
10
+
11
+ File.open(output_path, "w") do |f|
12
+ f.write(JSON.pretty_generate(json))
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def output_path
19
+ options[:output_path]
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,20 @@
1
+ require 'terminal-table'
2
+
3
+ module Xctracker
4
+ class StandardOutputReporter < AbstractReporter
5
+ def report!(executions)
6
+ filtered = filter_executions(executions)
7
+ puts table_for(filtered)
8
+ end
9
+
10
+ def table_for(executions)
11
+ Terminal::Table.new do |t|
12
+ t << ['File', 'Line', 'Method name', 'Time(ms)']
13
+ t << :separator
14
+ executions.each do |execution|
15
+ t << [execution.path, execution.line, execution.method_name, execution.time]
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,40 @@
1
+ require 'terminal-table'
2
+ require 'colorize'
3
+
4
+ module Xctracker
5
+ class Tracker
6
+ attr_writer :reporters
7
+ attr_reader :derived_data
8
+
9
+ def self.by_path(activity_log_path)
10
+ derived_data = DerivedData.new(activity_log_path)
11
+ Tracker.new(derived_data)
12
+ end
13
+
14
+ def self.by_product_name(product_name)
15
+ derived_data = DerivedData.by_product_name(product_name)
16
+ Tracker.new(derived_data)
17
+ end
18
+
19
+ def initialize(derived_data)
20
+ @derived_data = derived_data
21
+ end
22
+
23
+ def report!
24
+ if !derived_data.flag_enabled?
25
+ raise BuildFlagIsNotEnabled, "'-Xfrontend -debug-time-function-bodies' flag is not enabled"
26
+ end
27
+
28
+ reporters.each do |reporter|
29
+ reporter = reporter
30
+ reporter.report!(derived_data.executions)
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def reporters
37
+ @reporters ||= [StandardOutputReporter.new(limit: options[:limit], order: options[:order])]
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,3 @@
1
+ module Xctracker
2
+ VERSION = "0.1.0"
3
+ end
data/xctracker.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'xctracker/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "xctracker"
8
+ spec.version = Xctracker::VERSION
9
+ spec.authors = ["giginet"]
10
+ spec.email = ["giginet.net@gmail.com"]
11
+
12
+ spec.summary = %q{CLI to analyze build times of Swift projects}
13
+ spec.description = %q{xctracker parses activity logs generated by Xcode and reports build time of Swift projects}
14
+ spec.homepage = 'https://github.com/giginet/xctracker'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.6"
21
+ spec.add_development_dependency "rake", "~> 10.0"
22
+ spec.add_development_dependency "rspec"
23
+ spec.add_development_dependency "coveralls"
24
+
25
+ spec.add_dependency 'terminal-table'
26
+ spec.add_dependency 'colorize'
27
+ end
metadata ADDED
@@ -0,0 +1,150 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xctracker
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - giginet
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-12-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.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
+ - !ruby/object:Gem::Dependency
56
+ name: coveralls
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: terminal-table
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: colorize
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: xctracker parses activity logs generated by Xcode and reports build time
98
+ of Swift projects
99
+ email:
100
+ - giginet.net@gmail.com
101
+ executables:
102
+ - xctracker
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - ".coveralls.yml"
107
+ - ".gitignore"
108
+ - ".rspec"
109
+ - ".travis.yml"
110
+ - Gemfile
111
+ - LICENSE
112
+ - README.md
113
+ - Rakefile
114
+ - assets/build_flags.png
115
+ - assets/sample_output.png
116
+ - bin/xctracker
117
+ - lib/xctracker.rb
118
+ - lib/xctracker/derived_data.rb
119
+ - lib/xctracker/exceptions.rb
120
+ - lib/xctracker/execution.rb
121
+ - lib/xctracker/reporters/abstract_reporter.rb
122
+ - lib/xctracker/reporters/json_reporter.rb
123
+ - lib/xctracker/reporters/standard_output_reporter.rb
124
+ - lib/xctracker/tracker.rb
125
+ - lib/xctracker/version.rb
126
+ - xctracker.gemspec
127
+ homepage: https://github.com/giginet/xctracker
128
+ licenses: []
129
+ metadata: {}
130
+ post_install_message:
131
+ rdoc_options: []
132
+ require_paths:
133
+ - lib
134
+ required_ruby_version: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ required_rubygems_version: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ requirements: []
145
+ rubyforge_project:
146
+ rubygems_version: 2.5.1
147
+ signing_key:
148
+ specification_version: 4
149
+ summary: CLI to analyze build times of Swift projects
150
+ test_files: []