ipa_analyzer 0.1.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.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +35 -0
- data/LICENSE +22 -0
- data/README.md +19 -0
- data/_scripts/make.sh +26 -0
- data/bin/ipa_analyzer +113 -0
- data/ipa_analyzer.gemspec +27 -0
- data/lib/ipa_analyzer.rb +2 -0
- data/lib/ipa_analyzer/analyzer.rb +154 -0
- data/lib/ipa_analyzer/version.rb +3 -0
- metadata +124 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a7ff3fc2e0fd9c5325945dbc74f69529c05a6404
|
4
|
+
data.tar.gz: 3fcff8cfd50124ced9a7c2d8103a65a5e5d87068
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0aefb110eaa03fac338ce0ac516b93effe282628b7a7381e66c498b273a8e8b3e9c609bdf1a5a13d45da07b5690a66c27f62c92902c2babd0559fbfd5924c80a
|
7
|
+
data.tar.gz: 1648eb696b7f9f7c84ed659d0c674c6aed868791cfcd72e5cd4a9b0b7b2d2b7f548d6ebb20e99e843f6ddb8d83da5a1d7ce1191e4fe158e189fbb00e27d6a470
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
ipa_analyzer (0.1.0)
|
5
|
+
plist (~> 3.1, >= 3.1.0)
|
6
|
+
rubyzip (~> 1.1.7, >= 1.1.7)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
diff-lcs (1.2.5)
|
12
|
+
plist (3.1.0)
|
13
|
+
rake (10.4.2)
|
14
|
+
rspec (3.2.0)
|
15
|
+
rspec-core (~> 3.2.0)
|
16
|
+
rspec-expectations (~> 3.2.0)
|
17
|
+
rspec-mocks (~> 3.2.0)
|
18
|
+
rspec-core (3.2.0)
|
19
|
+
rspec-support (~> 3.2.0)
|
20
|
+
rspec-expectations (3.2.0)
|
21
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
22
|
+
rspec-support (~> 3.2.0)
|
23
|
+
rspec-mocks (3.2.0)
|
24
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
25
|
+
rspec-support (~> 3.2.0)
|
26
|
+
rspec-support (3.2.1)
|
27
|
+
rubyzip (1.1.7)
|
28
|
+
|
29
|
+
PLATFORMS
|
30
|
+
ruby
|
31
|
+
|
32
|
+
DEPENDENCIES
|
33
|
+
ipa_analyzer!
|
34
|
+
rake
|
35
|
+
rspec
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Bitrise
|
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,19 @@
|
|
1
|
+
# ipa_analyzer
|
2
|
+
|
3
|
+
iOS IPA file analyzer
|
4
|
+
|
5
|
+
**This code will be converted to a Ruby Gem
|
6
|
+
once the basic functionality is implemented**
|
7
|
+
|
8
|
+
|
9
|
+
## Usage example
|
10
|
+
|
11
|
+
bundle exec ruby ipa_analyzer.rb -i /path/to/app.ipa -p --info-plist --prov
|
12
|
+
|
13
|
+
This will collect and print both the embedded mobileprovisioning
|
14
|
+
and the Info.plist, in a pretty printed JSON output.
|
15
|
+
|
16
|
+
|
17
|
+
## Requirements
|
18
|
+
|
19
|
+
* OS: OS X (tested on 10.10 Yosemite)
|
data/_scripts/make.sh
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
#
|
4
|
+
# Prints the given command, then executes it
|
5
|
+
# Example: print_and_do_command echo 'hi'
|
6
|
+
#
|
7
|
+
function print_and_do_command {
|
8
|
+
echo " -> $ $@"
|
9
|
+
$@
|
10
|
+
}
|
11
|
+
|
12
|
+
#
|
13
|
+
# Print the given command, execute it
|
14
|
+
# and exit if error happened
|
15
|
+
function print_and_do_command_exit_on_error {
|
16
|
+
print_and_do_command $@
|
17
|
+
if [ $? -ne 0 ]; then
|
18
|
+
echo " [!] Failed!"
|
19
|
+
exit 1
|
20
|
+
fi
|
21
|
+
}
|
22
|
+
|
23
|
+
# test
|
24
|
+
print_and_do_command_exit_on_error rspec
|
25
|
+
# build
|
26
|
+
print_and_do_command_exit_on_error gem build ipa_analyzer.gemspec
|
data/bin/ipa_analyzer
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
$:.push File.expand_path("../../lib", __FILE__)
|
7
|
+
require 'ipa_analyzer'
|
8
|
+
|
9
|
+
|
10
|
+
# -------------------------
|
11
|
+
# --- Options
|
12
|
+
|
13
|
+
options = {
|
14
|
+
ipa_path: nil,
|
15
|
+
is_verbose: false,
|
16
|
+
is_pretty: false,
|
17
|
+
is_collect_provision_info: false,
|
18
|
+
is_collect_info_plist: false
|
19
|
+
}
|
20
|
+
|
21
|
+
opt_parser = OptionParser.new do |opt|
|
22
|
+
opt.banner = "Usage: ipa_analyzer.rb [OPTIONS]"
|
23
|
+
opt.separator ""
|
24
|
+
opt.separator "Options, the ones marked with * are required"
|
25
|
+
|
26
|
+
opt.on("-i","--ipa IPA_PATH", "*IPA file path") do |value|
|
27
|
+
options[:ipa_path] = value
|
28
|
+
end
|
29
|
+
|
30
|
+
opt.on("--prov","Collect Provisioning Profile (mobileprovision) information from the IPA") do
|
31
|
+
options[:is_collect_provision_info] = true
|
32
|
+
end
|
33
|
+
|
34
|
+
opt.on("--info-plist","Collect Info.plist information from the IPA") do
|
35
|
+
options[:is_collect_info_plist] = true
|
36
|
+
end
|
37
|
+
|
38
|
+
opt.on("-v","--verbose","Verbose output") do
|
39
|
+
options[:is_verbose] = true
|
40
|
+
end
|
41
|
+
|
42
|
+
opt.on("-p","--pretty","Pretty print output") do
|
43
|
+
options[:is_pretty] = true
|
44
|
+
end
|
45
|
+
|
46
|
+
opt.on("-h","--help","Shows this help message") do
|
47
|
+
puts opt_parser
|
48
|
+
exit 0
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
opt_parser.parse!
|
53
|
+
$options = options
|
54
|
+
|
55
|
+
|
56
|
+
# -------------------------
|
57
|
+
# --- Utils
|
58
|
+
|
59
|
+
def vputs(msg="")
|
60
|
+
if $options[:is_verbose]
|
61
|
+
puts msg
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
# -------------------------
|
67
|
+
# --- Main
|
68
|
+
|
69
|
+
vputs "options: #{options}"
|
70
|
+
|
71
|
+
raise "No IPA specified" unless options[:ipa_path]
|
72
|
+
raise "IPA specified but file does not exist at the provided path" unless File.exist? options[:ipa_path]
|
73
|
+
|
74
|
+
parsed_infos = {
|
75
|
+
mobileprovision: nil,
|
76
|
+
info_plist: nil
|
77
|
+
}
|
78
|
+
|
79
|
+
exit_code = 0
|
80
|
+
|
81
|
+
ipa_analyzer = IpaAnalyzer::Analyzer.new(options[:ipa_path])
|
82
|
+
begin
|
83
|
+
vputs " * Opening the IPA"
|
84
|
+
ipa_analyzer.open!
|
85
|
+
|
86
|
+
if options[:is_collect_provision_info]
|
87
|
+
vputs " * Collecting Provisioning Profile information"
|
88
|
+
parsed_infos[:mobileprovision] = ipa_analyzer.collect_provision_info()
|
89
|
+
raise "Failed to collect Provisioning Profile information" if parsed_infos[:mobileprovision].nil?
|
90
|
+
end
|
91
|
+
if options[:is_collect_info_plist]
|
92
|
+
vputs " * Collecting Info.plist information"
|
93
|
+
parsed_infos[:info_plist] = ipa_analyzer.collect_info_plist_info()
|
94
|
+
raise "Failed to collect Info.plist information" if parsed_infos[:info_plist].nil?
|
95
|
+
end
|
96
|
+
rescue => ex
|
97
|
+
puts
|
98
|
+
puts "Failed: #{ex}"
|
99
|
+
puts
|
100
|
+
exit_code = 1
|
101
|
+
raise ex
|
102
|
+
ensure
|
103
|
+
vputs " * Closing the IPA"
|
104
|
+
ipa_analyzer.close()
|
105
|
+
end
|
106
|
+
|
107
|
+
if options[:is_pretty]
|
108
|
+
puts JSON.pretty_generate(parsed_infos)
|
109
|
+
else
|
110
|
+
puts JSON.generate(parsed_infos)
|
111
|
+
end
|
112
|
+
|
113
|
+
exit exit_code
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
|
4
|
+
require "ipa_analyzer/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "ipa_analyzer"
|
8
|
+
s.authors = ["Bitrise", "Viktor Benei"]
|
9
|
+
s.email = 'letsconnect@bitrise.io'
|
10
|
+
s.license = "MIT"
|
11
|
+
s.homepage = "https://github.com/bitrise-io/ipa_analyzer"
|
12
|
+
s.version = IpaAnalyzer::VERSION
|
13
|
+
s.platform = Gem::Platform::RUBY
|
14
|
+
s.summary = "iOS .ipa analyzer"
|
15
|
+
s.description = "Analyze an iOS .ipa file. Can be used as a CLI and can print the information in JSON so it can be used by other tools."
|
16
|
+
|
17
|
+
s.add_runtime_dependency 'plist', '~> 3.1', '>= 3.1.0'
|
18
|
+
s.add_runtime_dependency 'rubyzip', '~> 1.1.7', '>= 1.1.7'
|
19
|
+
|
20
|
+
s.add_development_dependency "rspec"
|
21
|
+
s.add_development_dependency "rake"
|
22
|
+
|
23
|
+
s.files = Dir["./**/*"].reject { |file| file =~ /\.\/(bin|log|pkg|script|spec|test|vendor)/ }
|
24
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
25
|
+
s.executables = ['ipa_analyzer']
|
26
|
+
s.require_paths = ["lib"]
|
27
|
+
end
|
data/lib/ipa_analyzer.rb
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
require 'zip'
|
3
|
+
require 'zip/filesystem'
|
4
|
+
require 'plist'
|
5
|
+
|
6
|
+
module IpaAnalyzer
|
7
|
+
class Analyzer
|
8
|
+
def initialize(ipa_path)
|
9
|
+
@ipa_path = ipa_path
|
10
|
+
@ipa_zipfile = nil
|
11
|
+
@app_folder_path = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def open!
|
15
|
+
@ipa_zipfile = Zip::File.open(@ipa_path)
|
16
|
+
@app_folder_path = find_app_folder_in_ipa()
|
17
|
+
raise "No app folder found in the IPA" if @app_folder_path.nil?
|
18
|
+
end
|
19
|
+
|
20
|
+
def open?
|
21
|
+
return !@ipa_zipfile.nil?
|
22
|
+
end
|
23
|
+
|
24
|
+
def close
|
25
|
+
if self.open?
|
26
|
+
@ipa_zipfile.close()
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def collect_provision_info
|
31
|
+
raise "IPA is not open" unless self.open?
|
32
|
+
|
33
|
+
result = {
|
34
|
+
path_in_ipa: nil,
|
35
|
+
content: {}
|
36
|
+
}
|
37
|
+
mobileprovision_path = "#{@app_folder_path}/embedded.mobileprovision"
|
38
|
+
mobileprovision_entry = @ipa_zipfile.find_entry(mobileprovision_path)
|
39
|
+
|
40
|
+
raise "Embedded mobile provisioning file not found in (#{@ipa_path}) at path (#{mobileprovision_path})" unless mobileprovision_entry
|
41
|
+
result[:path_in_ipa] = "#{mobileprovision_entry}"
|
42
|
+
|
43
|
+
tempfile = Tempfile.new(::File.basename(mobileprovision_entry.name))
|
44
|
+
begin
|
45
|
+
@ipa_zipfile.extract(mobileprovision_entry, tempfile.path){ override = true }
|
46
|
+
plist = Plist::parse_xml(`security cms -D -i #{tempfile.path}`)
|
47
|
+
|
48
|
+
plist.each do |key, value|
|
49
|
+
next if key == "DeveloperCertificates"
|
50
|
+
|
51
|
+
parse_value = nil
|
52
|
+
case value
|
53
|
+
when Hash
|
54
|
+
parse_value = value
|
55
|
+
when Array
|
56
|
+
parse_value = value
|
57
|
+
else
|
58
|
+
parse_value = value.to_s
|
59
|
+
end
|
60
|
+
|
61
|
+
result[:content][key] = parse_value
|
62
|
+
end
|
63
|
+
|
64
|
+
rescue => e
|
65
|
+
puts e.message
|
66
|
+
result = nil
|
67
|
+
ensure
|
68
|
+
tempfile.close and tempfile.unlink
|
69
|
+
end
|
70
|
+
return result
|
71
|
+
end
|
72
|
+
|
73
|
+
def collect_info_plist_info
|
74
|
+
raise "IPA is not open" unless self.open?
|
75
|
+
|
76
|
+
result = {
|
77
|
+
path_in_ipa: nil,
|
78
|
+
content: {}
|
79
|
+
}
|
80
|
+
info_plist_entry = @ipa_zipfile.find_entry("#{@app_folder_path}/Info.plist")
|
81
|
+
|
82
|
+
raise "File 'Info.plist' not found in #{@ipa_path}" unless info_plist_entry
|
83
|
+
result[:path_in_ipa] = "#{info_plist_entry}"
|
84
|
+
|
85
|
+
tempfile = Tempfile.new(::File.basename(info_plist_entry.name))
|
86
|
+
begin
|
87
|
+
@ipa_zipfile.extract(info_plist_entry, tempfile.path){ override = true }
|
88
|
+
# convert from binary Plist to XML Plist
|
89
|
+
unless system("plutil -convert xml1 '#{tempfile.path}'")
|
90
|
+
raise "Failed to convert binary Plist to XML"
|
91
|
+
end
|
92
|
+
plist = Plist::parse_xml(tempfile.path)
|
93
|
+
|
94
|
+
plist.each do |key, value|
|
95
|
+
parse_value = nil
|
96
|
+
case value
|
97
|
+
when Hash
|
98
|
+
parse_value = value
|
99
|
+
when Array
|
100
|
+
parse_value = value
|
101
|
+
else
|
102
|
+
parse_value = value.to_s
|
103
|
+
end
|
104
|
+
|
105
|
+
result[:content][key] = parse_value
|
106
|
+
end
|
107
|
+
|
108
|
+
rescue => e
|
109
|
+
puts e.message
|
110
|
+
result = nil
|
111
|
+
ensure
|
112
|
+
tempfile.close and tempfile.unlink
|
113
|
+
end
|
114
|
+
return result
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
private
|
119
|
+
#
|
120
|
+
# Find the .app folder which contains both the "embedded.mobileprovision"
|
121
|
+
# and "Info.plist" files.
|
122
|
+
def find_app_folder_in_ipa
|
123
|
+
raise "IPA is not open" unless self.open?
|
124
|
+
|
125
|
+
# Check the most common location
|
126
|
+
app_folder_in_ipa = "Payload/#{File.basename(@ipa_path, File.extname(@ipa_path))}.app"
|
127
|
+
#
|
128
|
+
mobileprovision_entry = @ipa_zipfile.find_entry("#{app_folder_in_ipa}/embedded.mobileprovision")
|
129
|
+
info_plist_entry = @ipa_zipfile.find_entry("#{app_folder_in_ipa}/Info.plist")
|
130
|
+
#
|
131
|
+
if !mobileprovision_entry.nil? and !info_plist_entry.nil?
|
132
|
+
return app_folder_in_ipa
|
133
|
+
end
|
134
|
+
|
135
|
+
# It's somewhere else - let's find it!
|
136
|
+
@ipa_zipfile.dir.entries("Payload").each do |dir_entry|
|
137
|
+
if dir_entry =~ /.app$/
|
138
|
+
app_folder_in_ipa = "Payload/#{dir_entry}"
|
139
|
+
mobileprovision_entry = @ipa_zipfile.find_entry("#{app_folder_in_ipa}/embedded.mobileprovision")
|
140
|
+
info_plist_entry = @ipa_zipfile.find_entry("#{app_folder_in_ipa}/Info.plist")
|
141
|
+
|
142
|
+
if !mobileprovision_entry.nil? and !info_plist_entry.nil?
|
143
|
+
break
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
if !mobileprovision_entry.nil? and !info_plist_entry.nil?
|
149
|
+
return app_folder_in_ipa
|
150
|
+
end
|
151
|
+
return nil
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
metadata
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ipa_analyzer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bitrise
|
8
|
+
- Viktor Benei
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2015-02-11 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: plist
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '3.1'
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 3.1.0
|
24
|
+
type: :runtime
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: !ruby/object:Gem::Requirement
|
27
|
+
requirements:
|
28
|
+
- - "~>"
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '3.1'
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.1.0
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: rubyzip
|
36
|
+
requirement: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.1.7
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.1.7
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - "~>"
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: 1.1.7
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.1.7
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: rspec
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
type: :development
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: rake
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
type: :development
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
description: Analyze an iOS .ipa file. Can be used as a CLI and can print the information
|
83
|
+
in JSON so it can be used by other tools.
|
84
|
+
email: letsconnect@bitrise.io
|
85
|
+
executables:
|
86
|
+
- ipa_analyzer
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- "./Gemfile"
|
91
|
+
- "./Gemfile.lock"
|
92
|
+
- "./LICENSE"
|
93
|
+
- "./README.md"
|
94
|
+
- "./_scripts/make.sh"
|
95
|
+
- "./ipa_analyzer.gemspec"
|
96
|
+
- "./lib/ipa_analyzer.rb"
|
97
|
+
- "./lib/ipa_analyzer/analyzer.rb"
|
98
|
+
- "./lib/ipa_analyzer/version.rb"
|
99
|
+
- bin/ipa_analyzer
|
100
|
+
homepage: https://github.com/bitrise-io/ipa_analyzer
|
101
|
+
licenses:
|
102
|
+
- MIT
|
103
|
+
metadata: {}
|
104
|
+
post_install_message:
|
105
|
+
rdoc_options: []
|
106
|
+
require_paths:
|
107
|
+
- lib
|
108
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
requirements: []
|
119
|
+
rubyforge_project:
|
120
|
+
rubygems_version: 2.2.2
|
121
|
+
signing_key:
|
122
|
+
specification_version: 4
|
123
|
+
summary: iOS .ipa analyzer
|
124
|
+
test_files: []
|