run_loop_tcc 2.1.3

Sign up to get free protection for your applications and to get access to all the features.
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
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 92e7d3e3de5717d3d8d9af2eaf64b7e21c008899
4
+ data.tar.gz: 6307dfe028d32b2951502a42e5705beb62dc15f0
5
+ SHA512:
6
+ metadata.gz: 0213881ee96522fe96f450b7a3cbeea9f0493de793997e9eaeb706dc14161e43dc6ef49dfd54ac1586426fd10d400a170635a02147f16c1199ab1133136ed1b2
7
+ data.tar.gz: f5e66cb58ddea5e573454be69f3bce8b9438b7703a9739082a1a0d7bf8f17cdf04f22dc9de05ba6253cd187e2a1be1ec0be560ee88786dbb64d9acfd10d27f31
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ run-loop
2
+
3
+ Copyright (c) LessPainful ApS (https://www.lesspainful.com). All rights reserved.
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
13
+ all 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
21
+ THE SOFTWARE.
data/bin/run-loop ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+ require 'run_loop/cli/cli'
3
+ require 'run_loop/cli/errors'
4
+ require 'run_loop/environment'
5
+
6
+ begin
7
+ RunLoop::CLI::Tool.start
8
+ exit 0
9
+ rescue RunLoop::CLI::ValidationError, Thor::RequiredArgumentMissingError, Thor::UndefinedCommandError => e
10
+ puts e.message
11
+ exit 64
12
+ rescue Thor::Error => e
13
+ puts e.message
14
+ if RunLoop::Environment.debug?
15
+ puts e.backtrace.join("\n") if e.backtrace
16
+ p e.class
17
+ end
18
+ exit 70
19
+ end
@@ -0,0 +1,18 @@
1
+
2
+ module RunLoop
3
+ module Abstract
4
+ # @!visibility private
5
+ class AbstractMethodError < StandardError; end
6
+
7
+ # @!visibility private
8
+ def abstract_method!
9
+ if Kernel.method_defined?(:caller_locations)
10
+ method_name = icaller_locations.first.label
11
+ else
12
+ method_name = caller.first[/\`(.*)\'/, 1]
13
+ end
14
+
15
+ raise AbstractMethodError.new("Abstract method '#{method_name}'")
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,372 @@
1
+ module RunLoop
2
+ # A class for interacting with .app bundles.
3
+ class App
4
+
5
+ # @!attribute [r] path
6
+ # @return [String] The path to the app bundle .app
7
+ attr_reader :path
8
+
9
+ # Creates a new App instance.
10
+ #
11
+ # @note The `app_bundle_path` is expanded during initialization.
12
+ #
13
+ # @param [String] app_bundle_path A path to a .app
14
+ # @return [RunLoop::App] A instance of App with a path.
15
+ def initialize(app_bundle_path)
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. contain an Info.plist,
29
+ 4. and the app binary (CFBundleExecutable) must exist
30
+ }
31
+ end
32
+ end
33
+
34
+ # @!visibility private
35
+ def to_s
36
+ cf_bundle_version = bundle_version
37
+ cf_bundle_short_version = short_bundle_version
38
+
39
+ if cf_bundle_version && cf_bundle_short_version
40
+ version = "#{cf_bundle_version.to_s} / #{cf_bundle_short_version}"
41
+ elsif cf_bundle_version
42
+ version = cf_bundle_version.to_s
43
+ elsif cf_bundle_short_version
44
+ version = cf_bundle_short_version
45
+ else
46
+ version = ""
47
+ end
48
+
49
+ "#<APP #{bundle_identifier} #{version} #{path}>"
50
+ end
51
+
52
+ # @!visibility private
53
+ def inspect
54
+ to_s
55
+ end
56
+
57
+ # Is this a valid app?
58
+ def valid?
59
+ App.valid?(path)
60
+ end
61
+
62
+ # @!visibility private
63
+ def self.valid?(app_bundle_path)
64
+ return false if app_bundle_path.nil?
65
+
66
+ return false if !File.directory?(app_bundle_path)
67
+ return false if !File.extname(app_bundle_path) == ".app"
68
+
69
+ return false if !self.info_plist_exist?(app_bundle_path)
70
+ return false if !self.executable_file_exist?(app_bundle_path)
71
+ true
72
+ end
73
+
74
+ # Returns the Info.plist path.
75
+ # @raise [RuntimeError] If there is no Info.plist.
76
+ def info_plist_path
77
+ @info_plist_path ||= File.join(path, 'Info.plist')
78
+ end
79
+
80
+ # Inspects the app's Info.plist for the bundle identifier.
81
+ # @return [String] The value of CFBundleIdentifier.
82
+ # @raise [RuntimeError] If the plist cannot be read or the
83
+ # CFBundleIdentifier is empty or does not exist.
84
+ def bundle_identifier
85
+ identifier = plist_buddy.plist_read("CFBundleIdentifier", info_plist_path)
86
+ unless identifier
87
+ raise "Expected key 'CFBundleIdentifier' in '#{info_plist_path}'"
88
+ end
89
+ identifier
90
+ end
91
+
92
+ # Inspects the app's Info.plist for the executable name.
93
+ # @return [String] The value of CFBundleExecutable.
94
+ # @raise [RuntimeError] If the plist cannot be read or the
95
+ # CFBundleExecutable is empty or does not exist.
96
+ def executable_name
97
+ name = plist_buddy.plist_read("CFBundleExecutable", info_plist_path)
98
+ unless name
99
+ raise "Expected key 'CFBundleExecutable' in '#{info_plist_path}'"
100
+ end
101
+ name
102
+ end
103
+
104
+ # Returns the arches for the binary.
105
+ def arches
106
+ @arches ||= lipo.info
107
+ end
108
+
109
+ # True if the app has been built for the simulator
110
+ def simulator?
111
+ arches.include?("i386") || arches.include?("x86_64")
112
+ end
113
+
114
+ # True if the app has been built for physical devices
115
+ def physical_device?
116
+ arches.any? do |arch|
117
+ arch[/arm/, 0]
118
+ end
119
+ end
120
+
121
+ # Inspects the app's file for the server version
122
+ def calabash_server_version
123
+ version = nil
124
+ executables.each do |executable|
125
+ version = strings(executable).server_version
126
+ break if version
127
+ end
128
+ version
129
+ end
130
+
131
+ # @!visibility private
132
+ def codesign_info
133
+ RunLoop::Codesign.info(path)
134
+ end
135
+
136
+ # @!visibility private
137
+ def developer_signed?
138
+ RunLoop::Codesign.developer?(path)
139
+ end
140
+
141
+ # @!visibility private
142
+ def distribution_signed?
143
+ RunLoop::Codesign.distribution?(path)
144
+ end
145
+
146
+ # Returns the CFBundleShortVersionString of the app as Version instance.
147
+ #
148
+ # Apple docs:
149
+ #
150
+ # CFBundleShortVersionString specifies the release version number of the
151
+ # bundle, which identifies a released iteration of the app. The release
152
+ # version number is a string comprised of three period-separated integers.
153
+ #
154
+ # The first integer represents major revisions to the app, such as revisions
155
+ # that implement new features or major changes. The second integer denotes
156
+ # revisions that implement less prominent features. The third integer
157
+ # represents maintenance releases.
158
+ #
159
+ # The value for this key differs from the value for CFBundleVersion, which
160
+ # identifies an iteration (released or unreleased) of the app. This key can
161
+ # be localized by including it in your InfoPlist.strings files.
162
+ #
163
+ # @return [RunLoop::Version, nil] Returns a Version instance if the
164
+ # CFBundleShortVersion string is well formed and nil if not.
165
+ def marketing_version
166
+ string = plist_buddy.plist_read("CFBundleShortVersionString", info_plist_path)
167
+ begin
168
+ version = RunLoop::Version.new(string)
169
+ rescue
170
+ if string && string != ""
171
+ RunLoop.log_debug("CFBundleShortVersionString: '#{string}' is not a well formed version string")
172
+ else
173
+ RunLoop.log_debug("CFBundleShortVersionString is not defined in Info.plist")
174
+ end
175
+ version = nil
176
+ end
177
+ version
178
+ end
179
+
180
+ # See #marketing_version
181
+ alias_method :short_bundle_version, :marketing_version
182
+
183
+ # Returns the CFBundleVersionString of the app as Version instance.
184
+ #
185
+ # Apple docs:
186
+ #
187
+ # CFBundleVersion specifies the build version number of the bundle, which
188
+ # identifies an iteration (released or unreleased) of the bundle. The build
189
+ # version number should be a string comprised of three non-negative,
190
+ # period-separated integers with the first integer being greater than zero.
191
+ # The string should only contain numeric (0-9) and period (.) characters.
192
+ # Leading zeros are truncated from each integer and will be ignored (that
193
+ # is, 1.02.3 is equivalent to 1.2.3).
194
+ #
195
+ # @return [RunLoop::Version, nil] Returns a Version instance if the
196
+ # CFBundleVersion string is well formed and nil if not.
197
+ def build_version
198
+ string = plist_buddy.plist_read("CFBundleVersionString", info_plist_path)
199
+ begin
200
+ version = RunLoop::Version.new(string)
201
+ rescue
202
+ if string && string != ""
203
+ RunLoop.log_debug("CFBundleVersionString: '#{string}' is not a well formed version string")
204
+ else
205
+ RunLoop.log_debug("CFBundleVersionString is not defined in Info.plist")
206
+ end
207
+ version = nil
208
+ end
209
+ version
210
+ end
211
+
212
+ # See #build_version
213
+ alias_method :bundle_version, :build_version
214
+
215
+ # @!visibility private
216
+ # Collects the paths to executables in the bundle.
217
+ def executables
218
+ executables = []
219
+ Dir.glob("#{path}/**/*") do |file|
220
+ next if skip_executable_check?(file)
221
+ if otool(file).executable?
222
+ executables << file
223
+ end
224
+ end
225
+ executables
226
+ end
227
+
228
+ # Returns the sha1 of the application.
229
+ def sha1
230
+ RunLoop::Directory.directory_digest(path)
231
+ end
232
+
233
+ private
234
+
235
+ # @!visibility private
236
+ def self.info_plist_exist?(app_bundle_path)
237
+ info_plist = File.join(app_bundle_path, "Info.plist")
238
+ File.exist?(info_plist)
239
+ end
240
+
241
+ # @!visibility private
242
+ def self.executable_file_exist?(app_bundle_path)
243
+ return false if !self.info_plist_exist?(app_bundle_path)
244
+ info_plist = File.join(app_bundle_path, "Info.plist")
245
+ pbuddy = RunLoop::PlistBuddy.new
246
+ name = pbuddy.plist_read("CFBundleExecutable", info_plist)
247
+ if name
248
+ File.exist?(File.join(app_bundle_path, name))
249
+ else
250
+ false
251
+ end
252
+ end
253
+
254
+ # @!visibility private
255
+ def lipo
256
+ @lipo ||= RunLoop::Lipo.new(path)
257
+ end
258
+
259
+ # @!visibility private
260
+ def plist_buddy
261
+ @plist_buddy ||= RunLoop::PlistBuddy.new
262
+ end
263
+
264
+ # @!visibility private
265
+ # An otool factory.
266
+ def otool(file)
267
+ RunLoop::Otool.new(file)
268
+ end
269
+
270
+ # @!visibility private
271
+ # A strings factory
272
+ def strings(file)
273
+ RunLoop::Strings.new(file)
274
+ end
275
+
276
+ # @!visibility private
277
+ def skip_executable_check?(file)
278
+ File.directory?(file) ||
279
+ image?(file) ||
280
+ text?(file) ||
281
+ plist?(file) ||
282
+ lproj_asset?(file) ||
283
+ code_signing_asset?(file) ||
284
+ core_data_asset?(file) ||
285
+ font?(file)
286
+ end
287
+
288
+ # @!visibility private
289
+ def text?(file)
290
+ extension = File.extname(file)
291
+ filename = File.basename(file)
292
+
293
+ extension == ".txt" ||
294
+ extension == ".md" ||
295
+ extension == ".html" ||
296
+ extension == ".xml" ||
297
+ extension == ".json" ||
298
+ extension == ".yaml" ||
299
+ extension == ".yml" ||
300
+ extension == ".rtf" ||
301
+
302
+ ["NOTICE", "LICENSE", "README", "ABOUT"].any? do |elm|
303
+ filename[/#{elm}/]
304
+ end
305
+ end
306
+
307
+ # @!visibility private
308
+ def image?(file)
309
+ extension = File.extname(file)
310
+
311
+ extension == ".jpeg" ||
312
+ extension == ".jpg" ||
313
+ extension == ".gif" ||
314
+ extension == ".png" ||
315
+ extension == ".tiff" ||
316
+ extension == ".svg" ||
317
+ extension == ".pdf" ||
318
+ extension == ".car" ||
319
+ file[/iTunesArtwork/, 0]
320
+ end
321
+
322
+ # @!visibility private
323
+ def plist?(file)
324
+ File.extname(file) == ".plist"
325
+ end
326
+
327
+ # @!visibility private
328
+ def lproj_asset?(file)
329
+ extension = File.extname(file)
330
+ dir_extension = File.extname(File.dirname(file))
331
+
332
+ dir_extension == ".lproj" ||
333
+ dir_extension == ".storyboard" ||
334
+ dir_extension == ".storyboardc" ||
335
+ extension == ".strings" ||
336
+ extension == ".xib" ||
337
+ extension == ".nib"
338
+ end
339
+
340
+ # @!visibility private
341
+ def code_signing_asset?(file)
342
+ name = File.basename(file)
343
+ extension = File.extname(file)
344
+ dirname = File.basename(File.dirname(file))
345
+
346
+ name == "PkgInfo" ||
347
+ name == "embedded" ||
348
+ extension == ".mobileprovision" ||
349
+ extension == ".xcent" ||
350
+ dirname == "_CodeSignature"
351
+ end
352
+
353
+ # @!visibility private
354
+ def core_data_asset?(file)
355
+ extension = File.extname(file)
356
+ dir_extension = File.extname(File.dirname(file))
357
+
358
+ dir_extension == ".momd" ||
359
+ extension == ".mom" ||
360
+ extension == ".db" ||
361
+ extension == ".omo"
362
+ end
363
+
364
+ # @!visibility private
365
+ def font?(file)
366
+ extension = File.extname(file)
367
+
368
+ extension == ".tff" || extension == ".otf"
369
+ end
370
+ end
371
+ end
372
+
@@ -0,0 +1,68 @@
1
+ module RunLoop
2
+
3
+ # @!visibility private
4
+ # A class for managing an on-disk cache.
5
+ class Cache
6
+
7
+ require 'fileutils'
8
+
9
+ def initialize(path)
10
+ @path = path
11
+ end
12
+
13
+ def clear
14
+ raise NotImplementedError, 'Subclasses must implement #clear'
15
+ end
16
+
17
+ def refresh
18
+ raise NotImplementedError, 'Subclasses must implement #refresh'
19
+ end
20
+
21
+ # Reads the current cache.
22
+ # @return [Hash] A hash representation of the cache on disk.
23
+ def read
24
+ if File.exist? path
25
+ File.open(path) do |file|
26
+ Marshal.load(file)
27
+ end
28
+ else
29
+ write({})
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ attr_reader :path
36
+
37
+ # @!visibility private
38
+ #
39
+ # Writes `hash` as a serial object. The existing data is overwritten.
40
+ #
41
+ # @param [Hash] hash The hash to write.
42
+ # @raise [ArgumentError] The `hash` parameter must not be nil and it must
43
+ # be a Hash.
44
+ # @raise [TypeError] If the hash contains objects that cannot be written
45
+ # by Marshal.dump.
46
+ #
47
+ # @return [Hash] Returns the `hash` argument.
48
+ def write(hash)
49
+ if hash.nil?
50
+ raise ArgumentError, 'Expected the hash parameter to be non-nil'
51
+ end
52
+
53
+ unless hash.is_a?(Hash)
54
+ raise ArgumentError, "Expected #{hash} to a Hash, but it is a #{hash.class}"
55
+ end
56
+
57
+ directory = File.dirname(path)
58
+ unless File.exist?(directory)
59
+ FileUtils.mkdir_p(directory)
60
+ end
61
+
62
+ File.open(path, 'w') do |file|
63
+ Marshal.dump(hash, file)
64
+ end
65
+ hash
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,48 @@
1
+ require 'thor'
2
+ require 'run_loop'
3
+ require 'run_loop/cli/errors'
4
+ require 'run_loop/cli/instruments'
5
+ require 'run_loop/cli/simctl'
6
+ require "run_loop/cli/locale"
7
+ require "run_loop/cli/codesign"
8
+ require "run_loop/cli/tcc"
9
+
10
+ trap 'SIGINT' do
11
+ puts 'Trapped SIGINT - exiting'
12
+ exit 10
13
+ end
14
+
15
+ module RunLoop
16
+
17
+ module CLI
18
+
19
+ class Tool < Thor
20
+ include Thor::Actions
21
+
22
+ def self.exit_on_failure?
23
+ true
24
+ end
25
+
26
+ desc 'version', 'Prints version of the run_loop gem'
27
+ def version
28
+ puts RunLoop::VERSION
29
+ end
30
+
31
+ desc 'instruments', "Interact with Xcode's command-line instruments"
32
+ subcommand 'instruments', RunLoop::CLI::Instruments
33
+
34
+ desc 'simctl', "Interact with Xcode's command-line simctl"
35
+ subcommand 'simctl', RunLoop::CLI::Simctl
36
+
37
+ desc "locale", "Tools for interacting with locales"
38
+ subcommand "locale", RunLoop::CLI::Locale
39
+
40
+ desc "codesign", "Tools for interacting with codesign"
41
+ subcommand "codesign", RunLoop::CLI::Codesign
42
+
43
+ desc "tcc", "Tools for interacting with simulator privacy settings"
44
+ subcommand "tcc", RunLoop::CLI::TCC
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,24 @@
1
+ require "thor"
2
+ require "run_loop"
3
+ require "run_loop/cli/errors"
4
+
5
+ module RunLoop
6
+ module CLI
7
+ class Codesign < Thor
8
+
9
+ desc "info ARTIFACT", "Print codesign information about ARTIFACT (ipa, app, or library)"
10
+
11
+ def info(app_or_ipa)
12
+ extension = File.extname(app_or_ipa)
13
+
14
+ if extension == ".app"
15
+ puts RunLoop::App.new(app_or_ipa).codesign_info
16
+ elsif extension == ".ipa"
17
+ puts RunLoop::Ipa.new(app_or_ipa).codesign_info
18
+ else
19
+ puts RunLoop::Codesign.info(app_or_ipa)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,11 @@
1
+ require 'thor'
2
+
3
+ module RunLoop
4
+ module CLI
5
+ class ValidationError < Thor::InvocationError
6
+ end
7
+
8
+ class NotImplementedError < Thor::InvocationError
9
+ end
10
+ end
11
+ end