run_loop_tcc 2.1.3

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 (87) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/bin/run-loop +19 -0
  4. data/lib/run_loop/abstract.rb +18 -0
  5. data/lib/run_loop/app.rb +372 -0
  6. data/lib/run_loop/cache/cache.rb +68 -0
  7. data/lib/run_loop/cli/cli.rb +48 -0
  8. data/lib/run_loop/cli/codesign.rb +24 -0
  9. data/lib/run_loop/cli/errors.rb +11 -0
  10. data/lib/run_loop/cli/instruments.rb +160 -0
  11. data/lib/run_loop/cli/locale.rb +31 -0
  12. data/lib/run_loop/cli/simctl.rb +257 -0
  13. data/lib/run_loop/cli/tcc.rb +139 -0
  14. data/lib/run_loop/codesign.rb +76 -0
  15. data/lib/run_loop/core.rb +902 -0
  16. data/lib/run_loop/core_simulator.rb +960 -0
  17. data/lib/run_loop/detect_aut/detect.rb +185 -0
  18. data/lib/run_loop/detect_aut/errors.rb +126 -0
  19. data/lib/run_loop/detect_aut/xamarin_studio.rb +46 -0
  20. data/lib/run_loop/detect_aut/xcode.rb +157 -0
  21. data/lib/run_loop/device.rb +722 -0
  22. data/lib/run_loop/device_agent/app/CBX-Runner.app.zip +0 -0
  23. data/lib/run_loop/device_agent/bin/xctestctl +0 -0
  24. data/lib/run_loop/device_agent/cbxrunner.rb +156 -0
  25. data/lib/run_loop/device_agent/frameworks/Frameworks.zip +0 -0
  26. data/lib/run_loop/device_agent/frameworks.rb +65 -0
  27. data/lib/run_loop/device_agent/ipa/CBX-Runner.app.zip +0 -0
  28. data/lib/run_loop/device_agent/launcher.rb +51 -0
  29. data/lib/run_loop/device_agent/xcodebuild.rb +91 -0
  30. data/lib/run_loop/device_agent/xctestctl.rb +109 -0
  31. data/lib/run_loop/directory.rb +179 -0
  32. data/lib/run_loop/dnssd.rb +148 -0
  33. data/lib/run_loop/dot_dir.rb +87 -0
  34. data/lib/run_loop/dylib_injector.rb +145 -0
  35. data/lib/run_loop/encoding.rb +56 -0
  36. data/lib/run_loop/environment.rb +361 -0
  37. data/lib/run_loop/fifo.rb +40 -0
  38. data/lib/run_loop/host_cache.rb +128 -0
  39. data/lib/run_loop/http/error.rb +15 -0
  40. data/lib/run_loop/http/request.rb +44 -0
  41. data/lib/run_loop/http/retriable_client.rb +166 -0
  42. data/lib/run_loop/http/server.rb +17 -0
  43. data/lib/run_loop/instruments.rb +436 -0
  44. data/lib/run_loop/ipa.rb +142 -0
  45. data/lib/run_loop/l10n.rb +93 -0
  46. data/lib/run_loop/language.rb +63 -0
  47. data/lib/run_loop/lipo.rb +132 -0
  48. data/lib/run_loop/lldb.rb +52 -0
  49. data/lib/run_loop/locale.rb +101 -0
  50. data/lib/run_loop/logging.rb +111 -0
  51. data/lib/run_loop/otool.rb +76 -0
  52. data/lib/run_loop/patches/awesome_print.rb +17 -0
  53. data/lib/run_loop/physical_device/life_cycle.rb +268 -0
  54. data/lib/run_loop/plist_buddy.rb +189 -0
  55. data/lib/run_loop/process_terminator.rb +128 -0
  56. data/lib/run_loop/process_waiter.rb +117 -0
  57. data/lib/run_loop/regex.rb +19 -0
  58. data/lib/run_loop/shell.rb +103 -0
  59. data/lib/run_loop/sim_control.rb +1264 -0
  60. data/lib/run_loop/simctl.rb +275 -0
  61. data/lib/run_loop/sqlite.rb +61 -0
  62. data/lib/run_loop/strings.rb +88 -0
  63. data/lib/run_loop/tcc/TCC.db +0 -0
  64. data/lib/run_loop/tcc/tcc.rb +240 -0
  65. data/lib/run_loop/template.rb +61 -0
  66. data/lib/run_loop/version.rb +182 -0
  67. data/lib/run_loop/xcode.rb +318 -0
  68. data/lib/run_loop/xcrun.rb +107 -0
  69. data/lib/run_loop/xcuitest.rb +550 -0
  70. data/lib/run_loop.rb +230 -0
  71. data/plists/simctl/com.apple.UIAutomation.plist +0 -0
  72. data/plists/simctl/com.apple.UIAutomationPlugIn.plist +0 -0
  73. data/scripts/calabash_script_uia.js +28184 -0
  74. data/scripts/lib/json2.min.js +26 -0
  75. data/scripts/lib/log.js +26 -0
  76. data/scripts/lib/on_alert.js +224 -0
  77. data/scripts/read-cmd.sh +2 -0
  78. data/scripts/run_dismiss_location.js +89 -0
  79. data/scripts/run_loop_basic.js +34 -0
  80. data/scripts/run_loop_fast_uia.js +188 -0
  81. data/scripts/run_loop_host.js +117 -0
  82. data/scripts/run_loop_shared_element.js +125 -0
  83. data/scripts/timeout3 +23 -0
  84. data/scripts/udidetect +0 -0
  85. data/vendor-licenses/FBSimulatorControl.LICENSE +30 -0
  86. data/vendor-licenses/xctestctl.LICENSE +32 -0
  87. metadata +443 -0
@@ -0,0 +1,182 @@
1
+ module RunLoop
2
+ VERSION = "2.1.3"
3
+
4
+ # A model of a software release version that can be used to compare two versions.
5
+ #
6
+ # Calabash and RunLoop try very hard to comply with Semantic Versioning rules.
7
+ # However, the semantic versioning spec is incompatible with RubyGem's patterns
8
+ # for pre-release gems.
9
+ #
10
+ # > "But returning to the practical: No release version of SemVer is compatible with Rubygems." - _David Kellum_
11
+ #
12
+ # Calabash and RunLoop version numbers will be in the form `<major>.<minor>.<patch>[.pre<N>]`.
13
+ #
14
+ # @see http://semver.org/
15
+ # @see http://gravitext.com/2012/07/22/versioning.html
16
+ class Version
17
+
18
+ # @!attribute [rw] major
19
+ # @return [Integer] the major version
20
+ attr_accessor :major
21
+
22
+ # @!attribute [rw] minor
23
+ # @return [Integer] the minor version
24
+ attr_accessor :minor
25
+
26
+ # @!attribute [rw] patch
27
+ # @return [Integer] the patch version
28
+ attr_accessor :patch
29
+
30
+ # @!attribute [rw] pre
31
+ # @return [Boolean] true if this is a pre-release version
32
+ attr_accessor :pre
33
+
34
+ # @!attribute [rw] pre_version
35
+ # @return [Integer] if this is a pre-release version, returns the
36
+ # pre-release version; otherwise this is nil
37
+ attr_accessor :pre_version
38
+
39
+ # Creates a new Version instance with all the attributes set.
40
+ #
41
+ # @example
42
+ # version = Version.new(0.10.1)
43
+ # version.major => 0
44
+ # version.minor => 10
45
+ # version.patch => 1
46
+ # version.pre => false
47
+ # version.pre_version => nil
48
+ #
49
+ # @example
50
+ # version = Version.new(1.6.3.pre5)
51
+ # version.major => 1
52
+ # version.minor => 6
53
+ # version.patch => 3
54
+ # version.pre => true
55
+ # version.pre_version => 5
56
+ #
57
+ # @param [String] version the version string to parse.
58
+ # @raise [ArgumentError] if version is not in the form 5, 6.1, 7.1.2, 8.2.3.pre1
59
+ def initialize(version)
60
+ tokens = version.strip.split('.')
61
+ count = tokens.count
62
+ if tokens.empty?
63
+ raise ArgumentError, "expected '#{version}' to be like 5, 6.1, 7.1.2, 8.2.3.pre1"
64
+ end
65
+
66
+ if count < 4 and tokens.any? { |elm| elm =~ /\D/ }
67
+ raise ArgumentError, "expected '#{version}' to be like 5, 6.1, 7.1.2, 8.2.3.pre1"
68
+ end
69
+
70
+ if count == 4
71
+ @pre = tokens[3]
72
+ pre_tokens = @pre.scan(/\D+|\d+/)
73
+ @pre_version = pre_tokens[1].to_i if pre_tokens.count == 2
74
+ end
75
+
76
+ @major, @minor, @patch = version.split('.').map(&:to_i)
77
+ end
78
+
79
+ # Returns an string representation of this version.
80
+ # @return [String] a string in the form `<major>.<minor>.<patch>[.pre<N>]`
81
+ def to_s
82
+ str = [major, minor, patch].compact.join('.')
83
+ str = "#{str}.#{pre}" if pre
84
+ str
85
+ end
86
+
87
+ def inspect
88
+ "#<Version #{to_s}>"
89
+ end
90
+
91
+ # Compare this version to another for _object_ equality. This allows
92
+ # Version instances to be used as Hash keys.
93
+ # @param [Version] other the version to compare against.
94
+ def eql?(other)
95
+ hash == other.hash
96
+ end
97
+
98
+ # The hash method for this instance.
99
+ def hash
100
+ to_s.hash
101
+ end
102
+
103
+ # Compare this version to another for equality.
104
+ # @param [Version] other the version to compare against
105
+ # @return [Boolean] true if this Version is the same as `other`
106
+ def == (other)
107
+ Version.compare(self, other) == 0
108
+ end
109
+
110
+ # Compare this version to another for inequality.
111
+ # @param [Version] other the version to compare against
112
+ # @return [Boolean] true if this Version is not the same as `other`
113
+ def != (other)
114
+ Version.compare(self, other) != 0
115
+ end
116
+
117
+ # Is this version less-than another version?
118
+ # @param [Version] other the version to compare against
119
+ # @return [Boolean] true if this Version is less-than `other`
120
+ def < (other)
121
+ Version.compare(self, other) < 0
122
+ end
123
+
124
+ # Is this version greater-than another version?
125
+ # @param [Version] other the version to compare against
126
+ # @return [Boolean] true if this Version is greater-than `other`
127
+ def > (other)
128
+ Version.compare(self, other) > 0
129
+ end
130
+
131
+ # Is this version less-than or equal to another version?
132
+ # @param [Version] other the version to compare against
133
+ # @return [Boolean] true if this Version is less-than or equal `other`
134
+ def <= (other)
135
+ Version.compare(self, other) <= 0
136
+ end
137
+
138
+ # Is this version greater-than or equal to another version?
139
+ # @param [Version] other the version to compare against
140
+ # @return [Boolean] true if this Version is greater-than or equal `other`
141
+ def >= (other)
142
+ Version.compare(self, other) >= 0
143
+ end
144
+
145
+ # Compare version `a` to version `b`.
146
+ #
147
+ # @example
148
+ # compare Version.new(0.10.0), Version.new(0.9.0) => 1
149
+ # compare Version.new(0.9.0), Version.new(0.10.0) => -1
150
+ # compare Version.new(0.9.0), Version.new(0.9.0) => 0
151
+ #
152
+ # @return [Integer] an integer `(-1, 1)`
153
+ def self.compare(a, b)
154
+
155
+ if a.major != b.major
156
+ return a.major > b.major ? 1 : -1
157
+ end
158
+
159
+ if a.minor != b.minor
160
+ return a.minor.to_i > b.minor.to_i ? 1 : -1
161
+ end
162
+
163
+ if a.patch != b.patch
164
+ return a.patch.to_i > b.patch.to_i ? 1 : -1
165
+ end
166
+
167
+ return -1 if a.pre and (not a.pre_version) and b.pre_version
168
+ return 1 if a.pre_version and b.pre and (not b.pre_version)
169
+
170
+ return -1 if a.pre and (not b.pre)
171
+ return 1 if (not a.pre) and b.pre
172
+
173
+ return -1 if a.pre_version and (not b.pre_version)
174
+ return 1 if (not a.pre_version) and b.pre_version
175
+
176
+ if a.pre_version != b.pre_version
177
+ return a.pre_version.to_i > b.pre_version.to_i ? 1 : -1
178
+ end
179
+ 0
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,318 @@
1
+ require 'open3'
2
+
3
+ module RunLoop
4
+
5
+ # A model of the active Xcode version.
6
+ #
7
+ # @note All command line tools are run in the context of `xcrun`.
8
+ #
9
+ # Throughout this class's documentation, there are references to the
10
+ # _active version of Xcode_. The active Xcode version is the one returned
11
+ # by `xcrun xcodebuild`. The current Xcode version can be set using
12
+ # `xcode-select` or overridden using the `DEVELOPER_DIR`.
13
+ class Xcode
14
+
15
+ include RunLoop::Regex
16
+
17
+ # Returns a String representation.
18
+ def to_s
19
+ "#<Xcode #{version.to_s}>"
20
+ end
21
+
22
+ # Returns debug String representation
23
+ def inspect
24
+ to_s
25
+ end
26
+
27
+ # Returns a version instance for `Xcode 8.0`; used to check for the
28
+ # availability of features and paths to various items on the filesystem.
29
+ #
30
+ # @return [RunLoop::Version] 8.0
31
+ def v80
32
+ fetch_version(:v80)
33
+ end
34
+
35
+ # Returns a version instance for `Xcode 7.3`; used to check for the
36
+ # availability of features and paths to various items on the filesystem.
37
+ #
38
+ # @return [RunLoop::Version] 7.3
39
+ def v73
40
+ fetch_version(:v73)
41
+ end
42
+
43
+ # Returns a version instance for `Xcode 7.2`; used to check for the
44
+ # availability of features and paths to various items on the filesystem.
45
+ #
46
+ # @return [RunLoop::Version] 7.2
47
+ def v72
48
+ fetch_version(:v72)
49
+ end
50
+
51
+ # Returns a version instance for `Xcode 7.1`; used to check for the
52
+ # availability of features and paths to various items on the filesystem.
53
+ #
54
+ # @return [RunLoop::Version] 7.1
55
+ def v71
56
+ fetch_version(:v71)
57
+ end
58
+
59
+ # Returns a version instance for `Xcode 7.0`; used to check for the
60
+ # availability of features and paths to various items on the filesystem.
61
+ #
62
+ # @return [RunLoop::Version] 7.0
63
+ def v70
64
+ fetch_version(:v70)
65
+ end
66
+
67
+ # Returns a version instance for `Xcode 6.4`; used to check for the
68
+ # availability of features and paths to various items on the filesystem.
69
+ #
70
+ # @return [RunLoop::Version] 6.4
71
+ def v64
72
+ fetch_version(:v64)
73
+ end
74
+
75
+ # Returns a version instance for `Xcode 6.3`; used to check for the
76
+ # availability of features and paths to various items on the filesystem.
77
+ #
78
+ # @return [RunLoop::Version] 6.3
79
+ def v63
80
+ fetch_version(:v63)
81
+ end
82
+
83
+ # Returns a version instance for `Xcode 6.2`; used to check for the
84
+ # availability of features and paths to various items on the filesystem.
85
+ #
86
+ # @return [RunLoop::Version] 6.2
87
+ def v62
88
+ fetch_version(:v62)
89
+ end
90
+
91
+ # Returns a version instance for `Xcode 6.1`; used to check for the
92
+ # availability of features and paths to various items on the filesystem.
93
+ #
94
+ # @return [RunLoop::Version] 6.1
95
+ def v61
96
+ fetch_version(:v61)
97
+ end
98
+
99
+ # Returns a version instance for `Xcode 6.0`; used to check for the
100
+ # availability of features and paths to various items on the filesystem.
101
+ #
102
+ # @return [RunLoop::Version] 6.0
103
+ def v60
104
+ fetch_version(:v60)
105
+ end
106
+
107
+ # Returns a version instance for `Xcode 5.1`; used to check for the
108
+ # availability of features and paths to various items on the filesystem.
109
+ #
110
+ # @return [RunLoop::Version] 5.1
111
+ def v51
112
+ fetch_version(:v51)
113
+ end
114
+
115
+ # Returns a version instance for `Xcode 5.0`; used to check for the
116
+ # availability of features and paths to various items on the filesystem.
117
+ #
118
+ # @return [RunLoop::Version] 5.0
119
+ def v50
120
+ fetch_version(:v50)
121
+ end
122
+
123
+ # Is the active Xcode version 8.0 or above?
124
+ #
125
+ # @return [Boolean] `true` if the current Xcode version is >= 8.0
126
+ def version_gte_8?
127
+ version >= v80
128
+ end
129
+
130
+ # Is the active Xcode version 7.3 or above?
131
+ #
132
+ # @return [Boolean] `true` if the current Xcode version is >= 7.3
133
+ def version_gte_73?
134
+ version >= v73
135
+ end
136
+
137
+ # Is the active Xcode version 7.2 or above?
138
+ #
139
+ # @return [Boolean] `true` if the current Xcode version is >= 7.2
140
+ def version_gte_72?
141
+ version >= v72
142
+ end
143
+
144
+ # Is the active Xcode version 7.1 or above?
145
+ #
146
+ # @return [Boolean] `true` if the current Xcode version is >= 7.1
147
+ def version_gte_71?
148
+ version >= v71
149
+ end
150
+
151
+ # Is the active Xcode version 7 or above?
152
+ #
153
+ # @return [Boolean] `true` if the current Xcode version is >= 7.0
154
+ def version_gte_7?
155
+ version >= v70
156
+ end
157
+
158
+ # Is the active Xcode version 6.4 or above?
159
+ #
160
+ # @return [Boolean] `true` if the current Xcode version is >= 6.4
161
+ def version_gte_64?
162
+ version >= v64
163
+ end
164
+
165
+ # Is the active Xcode version 6.3 or above?
166
+ #
167
+ # @return [Boolean] `true` if the current Xcode version is >= 6.3
168
+ def version_gte_63?
169
+ version >= v63
170
+ end
171
+
172
+ # Is the active Xcode version 6.2 or above?
173
+ #
174
+ # @return [Boolean] `true` if the current Xcode version is >= 6.2
175
+ def version_gte_62?
176
+ version >= v62
177
+ end
178
+
179
+ # Is the active Xcode version 6.1 or above?
180
+ #
181
+ # @return [Boolean] `true` if the current Xcode version is >= 6.1
182
+ def version_gte_61?
183
+ version >= v61
184
+ end
185
+
186
+ # Is the active Xcode version 6 or above?
187
+ #
188
+ # @return [Boolean] `true` if the current Xcode version is >= 6.0
189
+ def version_gte_6?
190
+ version >= v60
191
+ end
192
+
193
+ # @deprecated 2.1.0
194
+ # Is the active Xcode version 5.1 or above?
195
+ #
196
+ # @return [Boolean] `true` if the current Xcode version is >= 5.1
197
+ def version_gte_51?
198
+ #RunLoop.deprecated("2.1.0", "No replacement")
199
+ version >= v51
200
+ end
201
+
202
+ # Returns the current version of Xcode.
203
+ #
204
+ # @return [RunLoop::Version] The current version of Xcode as reported by
205
+ # `xcrun xcodebuild -version`.
206
+ def version
207
+ @xcode_version ||= lambda do
208
+ execute_command(['-version']) do |stdout, _, _|
209
+ version_string = stdout.read.chomp[VERSION_REGEX, 0]
210
+ RunLoop::Version.new(version_string)
211
+ end
212
+ end.call
213
+ end
214
+
215
+ # Is this a beta version of Xcode?
216
+ #
217
+ # @note Relies on Xcode beta versions having and app bundle named Xcode-Beta.app
218
+ # @return [Boolean] True if the Xcode version is beta.
219
+ def beta?
220
+ developer_dir[/Xcode-[Bb]eta.app/, 0]
221
+ end
222
+
223
+ # Returns the path to the current developer directory.
224
+ #
225
+ # From the man pages:
226
+ #
227
+ # ```
228
+ # $ man xcode-select
229
+ # DEVELOPER_DIR
230
+ # Overrides the active developer directory. When DEVELOPER_DIR is set,
231
+ # its value will be used instead of the system-wide active developer
232
+ # directory.
233
+ #```
234
+ #
235
+ # @return [String] path to current developer directory
236
+ #
237
+ # @raise [RuntimeError] If path to Xcode.app/Contents/Developer
238
+ # cannot be determined.
239
+ def developer_dir
240
+ @xcode_developer_dir ||= lambda do
241
+ if RunLoop::Environment.developer_dir
242
+ path = RunLoop::Environment.developer_dir
243
+ else
244
+ path = xcode_select_path
245
+ end
246
+
247
+ if !File.directory?(path)
248
+ raise RuntimeError,
249
+ %Q{Cannot determine the active Xcode. Expected an Xcode here:
250
+
251
+ #{path}
252
+
253
+ Check the value of xcode-select:
254
+
255
+ # Does this resolve to a valid Xcode.app/Contents/Developer path?
256
+ $ xcode-select --print-path
257
+
258
+ Is the DEVELOPER_DIR variable set in your environment? You would
259
+ only use this if you have multiple Xcode's installed.
260
+
261
+ $ echo $DEVELOPER_DIR
262
+
263
+ See the man pages for xcrun and xcode-select for details.
264
+
265
+ $ man xcrun
266
+ $ man xcode-select
267
+ }
268
+ end
269
+ path
270
+ end.call
271
+ end
272
+
273
+ private
274
+
275
+ attr_reader :xcode_versions
276
+
277
+ def xcode_versions
278
+ @xcode_versions ||= {}
279
+ end
280
+
281
+ def fetch_version(key)
282
+ ensure_valid_version_key key
283
+ value = xcode_versions[key]
284
+
285
+ return value if value
286
+
287
+ string = key.to_s
288
+ string[0] = ''
289
+ version_string = string.split(/(?!^)/).join('.')
290
+ version = RunLoop::Version.new(version_string)
291
+ xcode_versions[key] = version
292
+ version
293
+ end
294
+
295
+ def ensure_valid_version_key(key)
296
+ string = key.to_s
297
+ if string.length != 3
298
+ raise "Expected version key '#{key}' to have exactly 3 characters"
299
+ end
300
+
301
+ unless string[/v\d{2}/, 0]
302
+ raise "Expected version key '#{key}' to match vXX pattern"
303
+ end
304
+ end
305
+
306
+ def execute_command(args)
307
+ Open3.popen3('xcrun', 'xcodebuild', *args) do |_, stdout, stderr, wait_thr|
308
+ yield stdout, stderr, wait_thr
309
+ end
310
+ end
311
+
312
+ def xcode_select_path
313
+ Open3.popen3('xcode-select', '--print-path') do |_, stdout, _, _|
314
+ stdout.read.chomp
315
+ end
316
+ end
317
+ end
318
+ end
@@ -0,0 +1,107 @@
1
+ module RunLoop
2
+ class Xcrun
3
+
4
+ require "command_runner"
5
+ require "run_loop/encoding"
6
+ include RunLoop::Encoding
7
+
8
+ # Controls the behavior of Xcrun#run_command_in_context.
9
+ #
10
+ # You can override these values if they do not work in your environment.
11
+ #
12
+ # For cucumber users, the best place to override would be in your
13
+ # features/support/env.rb.
14
+ #
15
+ # For example:
16
+ #
17
+ # RunLoop::Xcrun::DEFAULT_OPTIONS[:timeout] = 60
18
+ DEFAULT_OPTIONS = {
19
+ :timeout => 30,
20
+ :log_cmd => false
21
+ }
22
+
23
+ # Raised when Xcrun fails.
24
+ class Error < RuntimeError; end
25
+
26
+ # Raised when Xcrun times out.
27
+ class TimeoutError < RuntimeError; end
28
+
29
+ # Aliased to #exec, which will be removed in 3.0
30
+ def run_command_in_context(args, options={})
31
+ merged_options = DEFAULT_OPTIONS.merge(options)
32
+
33
+ timeout = merged_options[:timeout]
34
+
35
+ unless args.is_a?(Array)
36
+ raise ArgumentError,
37
+ "Expected args '#{args}' to be an Array, but found '#{args.class}'"
38
+ end
39
+
40
+ args.each do |arg|
41
+ unless arg.is_a?(String)
42
+ raise ArgumentError,
43
+ %Q{Expected arg '#{arg}' to be a String, but found '#{arg.class}'
44
+ IO.popen requires all arguments to be Strings.
45
+ }
46
+ end
47
+ end
48
+
49
+ cmd = "xcrun #{args.join(' ')}"
50
+
51
+ # Don't see your log?
52
+ # Commands are only logged when debugging.
53
+ RunLoop.log_unix_cmd(cmd) if merged_options[:log_cmd]
54
+
55
+ hash = {}
56
+
57
+ begin
58
+
59
+ start_time = Time.now
60
+ command_output = CommandRunner.run(['xcrun'] + args, timeout: timeout)
61
+
62
+ out = ensure_command_output_utf8(command_output[:out], cmd)
63
+ process_status = command_output[:status]
64
+
65
+ hash =
66
+ {
67
+ :out => out,
68
+ :pid => process_status.pid,
69
+ # nil if process was killed before completion
70
+ :exit_status => process_status.exitstatus
71
+ }
72
+
73
+ rescue RunLoop::Encoding::UTF8Error => e
74
+ raise e
75
+ rescue => e
76
+ elapsed = "%0.2f" % (Time.now - start_time)
77
+ raise Error,
78
+ %Q{Xcrun encountered an error after #{elapsed} seconds:
79
+
80
+ #{e}
81
+
82
+ executing this command:
83
+
84
+ #{cmd}
85
+ }
86
+ end
87
+
88
+ if hash[:exit_status].nil?
89
+ elapsed = "%0.2f" % (Time.now - start_time)
90
+ raise TimeoutError,
91
+ %Q{Xcrun timed out after #{elapsed} seconds executing
92
+
93
+ #{cmd}
94
+
95
+ with a timeout of #{timeout}
96
+ }
97
+ end
98
+
99
+ hash
100
+ end
101
+
102
+ # TODO Remove in 3.0
103
+ # https://github.com/calabash/run_loop/issues/478
104
+ alias_method :exec, :run_command_in_context
105
+ end
106
+ end
107
+