run_loop 2.0.5 → 2.0.6
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 +4 -4
- data/lib/run_loop.rb +2 -0
- data/lib/run_loop/app.rb +124 -20
- data/lib/run_loop/ipa.rb +22 -66
- data/lib/run_loop/otool.rb +76 -0
- data/lib/run_loop/strings.rb +88 -0
- data/lib/run_loop/version.rb +1 -1
- data/lib/run_loop/xcrun.rb +35 -6
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e713b8074f4a98cc789fe39327c63c675d8483cb
|
4
|
+
data.tar.gz: 98d467c958129c5a33efa0fe654088f38b0b7b0f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 810a32b9c38f9b720129ca06dc8a80cb6d92c4243d8bd7dc4dd62cee55600e19d68f9eb38d7c28643f9ed023d3437e1c9b35beb26a1e9f95a64b8de3a9308a23
|
7
|
+
data.tar.gz: 0963ce5adff45b9aae3b20cc2635000ea69ef166deef85956461c2808abca49a371140d8a42d911a622a4e88547fbd6e90c713ff63befeaf49087b921ecfb56a
|
data/lib/run_loop.rb
CHANGED
@@ -20,6 +20,8 @@ require 'run_loop/sim_control'
|
|
20
20
|
require 'run_loop/device'
|
21
21
|
require 'run_loop/instruments'
|
22
22
|
require 'run_loop/lipo'
|
23
|
+
require "run_loop/otool"
|
24
|
+
require "run_loop/strings"
|
23
25
|
require 'run_loop/cache/cache'
|
24
26
|
require 'run_loop/host_cache'
|
25
27
|
require 'run_loop/patches/awesome_print'
|
data/lib/run_loop/app.rb
CHANGED
@@ -14,6 +14,20 @@ module RunLoop
|
|
14
14
|
# @return [RunLoop::App] A instance of App with a path.
|
15
15
|
def initialize(app_bundle_path)
|
16
16
|
@path = File.expand_path(app_bundle_path)
|
17
|
+
|
18
|
+
if !App.valid?(app_bundle_path)
|
19
|
+
raise ArgumentError,
|
20
|
+
%Q{App does not exist at path or is not an app bundle.
|
21
|
+
|
22
|
+
#{app_bundle_path}
|
23
|
+
|
24
|
+
Bundle must:
|
25
|
+
|
26
|
+
1. be a directory that exists,
|
27
|
+
2. have a .app extension,
|
28
|
+
3. and contain an Info.plist.
|
29
|
+
}
|
30
|
+
end
|
17
31
|
end
|
18
32
|
|
19
33
|
# @!visibility private
|
@@ -28,19 +42,23 @@ module RunLoop
|
|
28
42
|
|
29
43
|
# Is this a valid app?
|
30
44
|
def valid?
|
31
|
-
|
32
|
-
|
33
|
-
|
45
|
+
App.valid?(path)
|
46
|
+
end
|
47
|
+
|
48
|
+
# @!visibility private
|
49
|
+
def self.valid?(app_bundle_path)
|
50
|
+
return false if app_bundle_path.nil?
|
51
|
+
|
52
|
+
File.exist?(app_bundle_path) &&
|
53
|
+
File.directory?(app_bundle_path) &&
|
54
|
+
File.extname(app_bundle_path) == '.app' &&
|
55
|
+
File.exist?(File.join(app_bundle_path, "Info.plist"))
|
34
56
|
end
|
35
57
|
|
36
58
|
# Returns the Info.plist path.
|
37
59
|
# @raise [RuntimeError] If there is no Info.plist.
|
38
60
|
def info_plist_path
|
39
|
-
|
40
|
-
unless File.exist?(info_plist)
|
41
|
-
raise "Expected an Info.plist at '#{path}'"
|
42
|
-
end
|
43
|
-
info_plist
|
61
|
+
@info_plist_path ||= File.join(path, 'Info.plist')
|
44
62
|
end
|
45
63
|
|
46
64
|
# Inspects the app's Info.plist for the bundle identifier.
|
@@ -69,20 +87,26 @@ module RunLoop
|
|
69
87
|
|
70
88
|
# Inspects the app's file for the server version
|
71
89
|
def calabash_server_version
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
90
|
+
version = nil
|
91
|
+
executables.each do |executable|
|
92
|
+
version = strings(executable).server_version
|
93
|
+
break if version
|
94
|
+
end
|
95
|
+
version
|
96
|
+
end
|
97
|
+
|
98
|
+
# @!visibility private
|
99
|
+
# Collects the paths to executables in the bundle.
|
100
|
+
def executables
|
101
|
+
executables = []
|
102
|
+
Dir.glob("#{path}/**/*") do |file|
|
103
|
+
next if File.directory?(file)
|
104
|
+
next if skip_executable_check?(file)
|
105
|
+
if otool(file).executable?
|
106
|
+
executables << file
|
82
107
|
end
|
83
|
-
else
|
84
|
-
raise 'Path is not valid'
|
85
108
|
end
|
109
|
+
executables
|
86
110
|
end
|
87
111
|
|
88
112
|
# Returns the sha1 of the application.
|
@@ -92,9 +116,89 @@ module RunLoop
|
|
92
116
|
|
93
117
|
private
|
94
118
|
|
119
|
+
# @!visibility private
|
95
120
|
def plist_buddy
|
96
121
|
@plist_buddy ||= RunLoop::PlistBuddy.new
|
97
122
|
end
|
98
123
|
|
124
|
+
# @!visibility private
|
125
|
+
# An otool factory.
|
126
|
+
def otool(file)
|
127
|
+
RunLoop::Otool.new(file)
|
128
|
+
end
|
129
|
+
|
130
|
+
# @!visibility private
|
131
|
+
# A strings factory
|
132
|
+
def strings(file)
|
133
|
+
RunLoop::Strings.new(file)
|
134
|
+
end
|
135
|
+
|
136
|
+
# @!visibility private
|
137
|
+
def skip_executable_check?(file)
|
138
|
+
image?(file) ||
|
139
|
+
text?(file) ||
|
140
|
+
plist?(file) ||
|
141
|
+
lproj_asset?(file) ||
|
142
|
+
code_signing_asset?(file) ||
|
143
|
+
core_data_asset?(file)
|
144
|
+
end
|
145
|
+
|
146
|
+
# @!visibility private
|
147
|
+
def text?(file)
|
148
|
+
extension = File.extname(file)
|
149
|
+
|
150
|
+
extension == ".txt" ||
|
151
|
+
extension == ".md" ||
|
152
|
+
extension == ".html" ||
|
153
|
+
extension == ".xml" ||
|
154
|
+
extension == ".json" ||
|
155
|
+
extension == ".yaml" ||
|
156
|
+
extension == ".yml" ||
|
157
|
+
extension == ".rtf" ||
|
158
|
+
file[/NOTICE|LICENSE|README|ABOUT/, 0]
|
159
|
+
end
|
160
|
+
|
161
|
+
# @!visibility private
|
162
|
+
def image?(file)
|
163
|
+
file[/jpeg|jpg|gif|png|tiff|svg|pdf|car|iTunesArtwork/, 0]
|
164
|
+
end
|
165
|
+
|
166
|
+
# @!visibility private
|
167
|
+
def plist?(file)
|
168
|
+
File.extname(file) == ".plist"
|
169
|
+
end
|
170
|
+
|
171
|
+
# @!visibility private
|
172
|
+
def lproj_asset?(file)
|
173
|
+
extension = File.extname(file)
|
174
|
+
|
175
|
+
file[/lproj/, 0] ||
|
176
|
+
file[/storyboard/, 0] ||
|
177
|
+
extension == ".strings" ||
|
178
|
+
extension == ".xib" ||
|
179
|
+
extension == ".nib"
|
180
|
+
end
|
181
|
+
|
182
|
+
# @!visibility private
|
183
|
+
def code_signing_asset?(file)
|
184
|
+
name = File.basename(file)
|
185
|
+
extension = File.extname(file)
|
186
|
+
|
187
|
+
name == "PkgInfo" ||
|
188
|
+
name == "embedded" ||
|
189
|
+
extension == ".mobileprovision" ||
|
190
|
+
extension == ".xcent" ||
|
191
|
+
file[/_CodeSignature/, 0]
|
192
|
+
end
|
193
|
+
|
194
|
+
# @!visibility private
|
195
|
+
def core_data_asset?(file)
|
196
|
+
extension = File.extname(file)
|
197
|
+
|
198
|
+
file[/momd/, 0] ||
|
199
|
+
extension == ".mom" ||
|
200
|
+
extension == ".db"
|
201
|
+
end
|
99
202
|
end
|
100
203
|
end
|
204
|
+
|
data/lib/run_loop/ipa.rb
CHANGED
@@ -2,18 +2,11 @@ module RunLoop
|
|
2
2
|
# A model of the an .ipa - a application binary for iOS devices.
|
3
3
|
class Ipa
|
4
4
|
|
5
|
-
|
6
5
|
# The path to this .ipa.
|
7
6
|
# @!attribute [r] path
|
8
7
|
# @return [String] A path to this .ipa.
|
9
8
|
attr_reader :path
|
10
9
|
|
11
|
-
# The bundle identifier of this ipa.
|
12
|
-
# @!attribute [r] bundle_identifier
|
13
|
-
# @return [String] The bundle identifier of this ipa; obtained by inspecting
|
14
|
-
# the app's Info.plist.
|
15
|
-
attr_reader :bundle_identifier
|
16
|
-
|
17
10
|
# Create a new ipa instance.
|
18
11
|
# @param [String] path_to_ipa The path the .ipa file.
|
19
12
|
# @return [Calabash::Ipa] A new ipa instance.
|
@@ -42,96 +35,59 @@ module RunLoop
|
|
42
35
|
|
43
36
|
# The bundle identifier of this ipa.
|
44
37
|
# @return [String] A string representation of this ipa's CFBundleIdentifier
|
45
|
-
# @raise [RuntimeError] If ipa does not expand into a Payload/<app name>.app
|
46
|
-
# directory.
|
47
|
-
# @raise [RuntimeError] If an Info.plist does exist in the .app.
|
48
38
|
def bundle_identifier
|
49
|
-
|
50
|
-
raise "Expected a '#{File.basename(path).split('.').first}.app'\nat path '#{payload_dir}'"
|
51
|
-
end
|
52
|
-
|
53
|
-
@bundle_identifier ||= lambda {
|
54
|
-
info_plist_path = File.join(bundle_dir, 'Info.plist')
|
55
|
-
unless File.exist? info_plist_path
|
56
|
-
raise "Expected an 'Info.plist' at '#{bundle_dir}'"
|
57
|
-
end
|
58
|
-
identifier = plist_buddy.plist_read('CFBundleIdentifier', info_plist_path)
|
59
|
-
|
60
|
-
unless identifier
|
61
|
-
raise "Expected key 'CFBundleIdentifier' in '#{info_plist_path}'"
|
62
|
-
end
|
63
|
-
identifier
|
64
|
-
}.call
|
39
|
+
app.bundle_identifier
|
65
40
|
end
|
66
41
|
|
67
42
|
# Inspects the app's Info.plist for the executable name.
|
68
43
|
# @return [String] The value of CFBundleExecutable.
|
69
|
-
# @raise [RuntimeError] If the plist cannot be read or the
|
70
|
-
# CFBundleExecutable is empty or does not exist.
|
71
44
|
def executable_name
|
72
|
-
|
73
|
-
raise "Expected a '#{File.basename(path).split('.').first}.app'\nat path '#{payload_dir}'"
|
74
|
-
end
|
75
|
-
|
76
|
-
@executable_name ||= lambda {
|
77
|
-
info_plist_path = File.join(bundle_dir, 'Info.plist')
|
78
|
-
unless File.exist? info_plist_path
|
79
|
-
raise "Expected an 'Info.plist' at '#{bundle_dir}'"
|
80
|
-
end
|
81
|
-
name = plist_buddy.plist_read('CFBundleExecutable', info_plist_path)
|
82
|
-
|
83
|
-
unless name
|
84
|
-
raise "Expected key 'CFBundleExecutable' in '#{info_plist_path}'"
|
85
|
-
end
|
86
|
-
name
|
87
|
-
}.call
|
45
|
+
app.executable_name
|
88
46
|
end
|
89
47
|
|
90
|
-
# Inspects the app's
|
48
|
+
# Inspects the app's executables for the server version
|
49
|
+
# @return[RunLoop::Version] a version instance
|
91
50
|
def calabash_server_version
|
92
|
-
|
93
|
-
raise "Expected a '#{File.basename(path).split('.').first}.app'\nat path '#{payload_dir}'"
|
94
|
-
else
|
95
|
-
if !executable_name.nil? && executable_name != ''
|
96
|
-
path_to_bin = File.join(bundle_dir, executable_name)
|
97
|
-
xcrun ||= RunLoop::Xcrun.new
|
98
|
-
hash = xcrun.exec(["strings", path_to_bin])
|
99
|
-
unless hash.nil?
|
100
|
-
version_str = hash[:out][/CALABASH VERSION: \d+\.\d+\.\d+/, 0]
|
101
|
-
unless version_str.nil? || version_str == ""
|
102
|
-
server_ver = version_str.split(":")[1].delete(' ')
|
103
|
-
RunLoop::Version.new(server_ver)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
51
|
+
app.calabash_server_version
|
108
52
|
end
|
109
53
|
|
110
54
|
private
|
111
55
|
|
56
|
+
# @!visibility private
|
112
57
|
def tmpdir
|
113
58
|
@tmpdir ||= Dir.mktmpdir
|
114
59
|
end
|
115
60
|
|
61
|
+
# @!visibility private
|
116
62
|
def payload_dir
|
117
|
-
@payload_dir ||= lambda
|
63
|
+
@payload_dir ||= lambda do
|
118
64
|
FileUtils.cp(path, tmpdir)
|
119
65
|
zip_path = File.join(tmpdir, File.basename(path))
|
120
66
|
Dir.chdir(tmpdir) do
|
121
67
|
system('unzip', *['-q', zip_path])
|
122
68
|
end
|
123
69
|
File.join(tmpdir, 'Payload')
|
124
|
-
|
70
|
+
end.call
|
125
71
|
end
|
126
72
|
|
73
|
+
# @!visibility private
|
127
74
|
def bundle_dir
|
128
|
-
@bundle_dir ||= lambda
|
129
|
-
Dir.glob(File.join(payload_dir, '*')).detect
|
130
|
-
|
75
|
+
@bundle_dir ||= lambda do
|
76
|
+
Dir.glob(File.join(payload_dir, '*')).detect do |f|
|
77
|
+
File.directory?(f) && f.end_with?('.app')
|
78
|
+
end
|
79
|
+
end.call
|
80
|
+
end
|
81
|
+
|
82
|
+
# @!visibility private
|
83
|
+
def app
|
84
|
+
@app ||= RunLoop::App.new(bundle_dir)
|
131
85
|
end
|
132
86
|
|
87
|
+
# @!visibility private
|
133
88
|
def plist_buddy
|
134
89
|
@plist_buddy ||= RunLoop::PlistBuddy.new
|
135
90
|
end
|
136
91
|
end
|
137
92
|
end
|
93
|
+
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module RunLoop
|
2
|
+
# @!visibility private
|
3
|
+
#
|
4
|
+
# A class for interacting with otool
|
5
|
+
class Otool
|
6
|
+
|
7
|
+
# @!visibility private
|
8
|
+
attr_reader :path
|
9
|
+
|
10
|
+
# @!visibility private
|
11
|
+
def initialize(path)
|
12
|
+
@path = path
|
13
|
+
|
14
|
+
if !Otool.valid_path?(path)
|
15
|
+
raise ArgumentError,
|
16
|
+
%Q{File:
|
17
|
+
|
18
|
+
#{path}
|
19
|
+
|
20
|
+
must exist and not be a directory.
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# @!visibility private
|
26
|
+
def to_s
|
27
|
+
"#<OTOOL: #{path}>"
|
28
|
+
end
|
29
|
+
|
30
|
+
# @!visibility private
|
31
|
+
def inspect
|
32
|
+
to_s
|
33
|
+
end
|
34
|
+
|
35
|
+
# @!visibility private
|
36
|
+
def executable?
|
37
|
+
!arch_info[/is not an object file/, 0]
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# @!visibility private
|
43
|
+
def arch_info
|
44
|
+
args = ["otool", "-hv", "-arch", "all", path]
|
45
|
+
opts = { :log_cmd => true }
|
46
|
+
|
47
|
+
hash = xcrun.exec(args, opts)
|
48
|
+
|
49
|
+
if hash[:exit_status] != 0
|
50
|
+
raise RuntimeError,
|
51
|
+
%Q{Could not get arch info from file:
|
52
|
+
|
53
|
+
#{path}
|
54
|
+
|
55
|
+
#{args.join(" ")}
|
56
|
+
|
57
|
+
exited #{hash[:exit_status]} with the following output:
|
58
|
+
|
59
|
+
#{hash[:out]}
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
@arch_info = hash[:out]
|
64
|
+
end
|
65
|
+
|
66
|
+
# @!visibility private
|
67
|
+
def self.valid_path?(path)
|
68
|
+
File.exist?(path) && !File.directory?(path)
|
69
|
+
end
|
70
|
+
|
71
|
+
# @!visibility private
|
72
|
+
def xcrun
|
73
|
+
RunLoop::Xcrun.new
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module RunLoop
|
2
|
+
# @!visibility private
|
3
|
+
#
|
4
|
+
# A class for interacting with the strings tool
|
5
|
+
class Strings
|
6
|
+
|
7
|
+
# @!visibility private
|
8
|
+
attr_reader :path
|
9
|
+
|
10
|
+
# @!visibility private
|
11
|
+
def initialize(path)
|
12
|
+
@path = path
|
13
|
+
|
14
|
+
if !Strings.valid_path?(path)
|
15
|
+
raise ArgumentError,
|
16
|
+
%Q{File:
|
17
|
+
|
18
|
+
#{path}
|
19
|
+
|
20
|
+
must exist and not be a directory.
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# @!visibility private
|
26
|
+
def to_s
|
27
|
+
"#<STRINGS: #{path}>"
|
28
|
+
end
|
29
|
+
|
30
|
+
# @!visibility private
|
31
|
+
def inspect
|
32
|
+
to_s
|
33
|
+
end
|
34
|
+
|
35
|
+
# @!visibility private
|
36
|
+
#
|
37
|
+
# @return [RunLoop::Version] A version instance or nil if the file
|
38
|
+
# at path does not contain server version information.
|
39
|
+
def server_version
|
40
|
+
regex = /CALABASH VERSION: (\d+\.\d+\.\d+(\.pre\d+)?)/
|
41
|
+
match = dump[regex, 0]
|
42
|
+
|
43
|
+
if match
|
44
|
+
str = match.split(":")[1]
|
45
|
+
RunLoop::Version.new(str)
|
46
|
+
else
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
# @!visibility private
|
54
|
+
def dump
|
55
|
+
args = ["strings", path]
|
56
|
+
opts = { :log_cmd => true }
|
57
|
+
|
58
|
+
hash = xcrun.exec(args, opts)
|
59
|
+
|
60
|
+
if hash[:exit_status] != 0
|
61
|
+
raise RuntimeError,
|
62
|
+
%Q{Could not get strings info from file:
|
63
|
+
|
64
|
+
#{path}
|
65
|
+
|
66
|
+
#{args.join(" ")}
|
67
|
+
|
68
|
+
exited #{hash[:exit_status]} with the following output:
|
69
|
+
|
70
|
+
#{hash[:out]}
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
@dump = hash[:out]
|
75
|
+
end
|
76
|
+
|
77
|
+
# @!visibility private
|
78
|
+
def self.valid_path?(path)
|
79
|
+
File.exist?(path) && !File.directory?(path)
|
80
|
+
end
|
81
|
+
|
82
|
+
# @!visibility private
|
83
|
+
def xcrun
|
84
|
+
RunLoop::Xcrun.new
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
data/lib/run_loop/version.rb
CHANGED
data/lib/run_loop/xcrun.rb
CHANGED
@@ -21,6 +21,8 @@ module RunLoop
|
|
21
21
|
# Raised when Xcrun fails.
|
22
22
|
class Error < RuntimeError; end
|
23
23
|
|
24
|
+
# Raised when the output of the command cannot be coerced to UTF8
|
25
|
+
class UTF8Error < RuntimeError; end
|
24
26
|
|
25
27
|
# Raised when Xcrun times out.
|
26
28
|
class TimeoutError < RuntimeError; end
|
@@ -58,12 +60,7 @@ IO.popen requires all arguments to be Strings.
|
|
58
60
|
start_time = Time.now
|
59
61
|
command_output = CommandRunner.run(['xcrun'] + args, timeout: timeout)
|
60
62
|
|
61
|
-
|
62
|
-
out = command_output[:out].force_encoding('utf-8').chomp
|
63
|
-
else
|
64
|
-
out = ''
|
65
|
-
end
|
66
|
-
|
63
|
+
out = encode_utf8_or_raise(command_output[:out], cmd)
|
67
64
|
process_status = command_output[:status]
|
68
65
|
|
69
66
|
hash =
|
@@ -74,6 +71,8 @@ IO.popen requires all arguments to be Strings.
|
|
74
71
|
:exit_status => process_status.exitstatus
|
75
72
|
}
|
76
73
|
|
74
|
+
rescue UTF8Error => e
|
75
|
+
raise e
|
77
76
|
rescue => e
|
78
77
|
elapsed = "%0.2f" % (Time.now - start_time)
|
79
78
|
raise Error,
|
@@ -100,5 +99,35 @@ with a timeout of #{timeout}
|
|
100
99
|
|
101
100
|
hash
|
102
101
|
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
# @!visibility private
|
106
|
+
def encode_utf8_or_raise(string, command)
|
107
|
+
return '' if !string
|
108
|
+
|
109
|
+
utf8 = string.force_encoding("UTF-8").chomp
|
110
|
+
|
111
|
+
return utf8 if utf8.valid_encoding?
|
112
|
+
|
113
|
+
encoded = utf8.encode('UTF-8', 'UTF-8', invalid: :replace, undef: :replace, replace: '')
|
114
|
+
|
115
|
+
return encoded if encoded.valid_encoding?
|
116
|
+
|
117
|
+
raise UTF8Error, %Q{
|
118
|
+
Could not force UTF-8 encoding on this string:
|
119
|
+
|
120
|
+
#{string}
|
121
|
+
|
122
|
+
which is the output of this command:
|
123
|
+
|
124
|
+
#{command}
|
125
|
+
|
126
|
+
Please file an issue with a stacktrace and the text of this error.
|
127
|
+
|
128
|
+
https://github.com/calabash/run_loop/issues
|
129
|
+
}
|
130
|
+
end
|
103
131
|
end
|
104
132
|
end
|
133
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: run_loop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Karl Krukow
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-02-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -295,6 +295,7 @@ files:
|
|
295
295
|
- lib/run_loop/lldb.rb
|
296
296
|
- lib/run_loop/locale.rb
|
297
297
|
- lib/run_loop/logging.rb
|
298
|
+
- lib/run_loop/otool.rb
|
298
299
|
- lib/run_loop/patches/awesome_print.rb
|
299
300
|
- lib/run_loop/plist_buddy.rb
|
300
301
|
- lib/run_loop/process_terminator.rb
|
@@ -302,6 +303,7 @@ files:
|
|
302
303
|
- lib/run_loop/regex.rb
|
303
304
|
- lib/run_loop/sim_control.rb
|
304
305
|
- lib/run_loop/simctl/plists.rb
|
306
|
+
- lib/run_loop/strings.rb
|
305
307
|
- lib/run_loop/template.rb
|
306
308
|
- lib/run_loop/version.rb
|
307
309
|
- lib/run_loop/xcode.rb
|