forked from realm/realm-swift
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreset-simulators.rb
executable file
·189 lines (161 loc) · 5.78 KB
/
reset-simulators.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#!/usr/bin/ruby
require 'json'
require 'open3'
prelaunch_simulator = ARGV[0] || ''
def platform_for_runtime(runtime)
runtime['identifier'].gsub(/com.apple.CoreSimulator.SimRuntime.([^-]+)-.*/, '\1')
end
def platform_for_device_type(device_type)
case device_type['identifier']
when /Watch/
'watchOS'
when /TV/
'tvOS'
else
'iOS'
end
end
def simctl(args)
# When running on a machine with Xcode 11 installed, Xcode 10 sometimes
# incorrectly thinks that it has not completed its first-run installation.
# This results in it printing errors related to that to stdout in front of
# the actual JSON output that we want.
Open3.popen3('xcrun simctl ' + args) do |stdin, stdout, strerr, wait_thr|
while line = stdout.gets
if not line.start_with? 'Install'
return line + stdout.read, wait_thr.value.exitstatus
end
end
end
end
def wait_for_core_simulator_service
# Run until we get a result since switching simulator versions often causes CoreSimulatorService to throw an exception.
while simctl('list devices')[0].empty?
end
end
def running_devices(devices)
devices.select { |device| device['state'] != 'Shutdown' }
end
def shutdown_simulator_devices(devices)
# Shut down any simulators that need it.
running_devices(devices).each do |device|
puts "Shutting down simulator #{device['udid']}"
system("xcrun simctl shutdown #{device['udid']}") or puts " Failed to shut down simulator #{device['udid']}"
end
end
attempts = 0
begin
# Kill all the current simulator processes as they may be from a different Xcode version
print 'Killing running Simulator processes...'
while system('pgrep -q Simulator')
system('pkill Simulator 2>/dev/null')
# CoreSimulatorService doesn't exit when sent SIGTERM
system('pkill -9 Simulator 2>/dev/null')
end
wait_for_core_simulator_service
puts ' done!'
print 'Shut down existing simulator devices...'
# Shut down any running simulator devices. This may take multiple attempts if some
# simulators are currently in the process of booting or being created.
all_available_devices = []
(0..5).each do |shutdown_attempt|
begin
devices_json = simctl('list devices -j')[0]
all_devices = JSON.parse(devices_json)['devices'].flat_map { |_, devices| devices }
rescue JSON::ParserError
sleep shutdown_attempt if shutdown_attempt > 0
next
end
# Exclude devices marked as unavailable as they're from a different version of Xcode.
all_available_devices = all_devices.reject { |device| device['availability'] =~ /unavailable/ }
break if running_devices(all_available_devices).empty?
shutdown_simulator_devices all_available_devices
sleep shutdown_attempt if shutdown_attempt > 0
end
puts ' done!'
# Delete all simulators.
print 'Deleting all simulators...'
(0..5).each do |delete_attempt|
break if all_available_devices.empty?
all_available_devices.each do |device|
simctl("delete #{device['udid']}")
end
begin
devices_json = simctl('list devices -j')[0]
all_devices = JSON.parse(devices_json)['devices'].flat_map { |_, devices| devices }
rescue JSON::ParserError
sleep shutdown_attempt if shutdown_attempt > 0
next
end
all_available_devices = all_devices.reject { |device| device['availability'] =~ /unavailable/ }
break if all_available_devices.empty?
end
puts ' done!'
if not all_available_devices.empty?
raise "Failed to delete devices #{all_available_devices}"
end
# Recreate all simulators.
runtimes = JSON.parse(simctl('list runtimes -j')[0])['runtimes']
device_types = JSON.parse(simctl('list devicetypes -j')[0])['devicetypes']
runtimes_by_platform = Hash.new { |hash, key| hash[key] = [] }
runtimes.each do |runtime|
next unless runtime['availability'] == '(available)' || runtime['isAvailable'] == true
runtimes_by_platform[platform_for_runtime(runtime)] << runtime
end
firstOnly = prelaunch_simulator == '-firstOnly'
print 'Creating fresh simulators...'
device_types.each do |device_type|
platform = platform_for_device_type(device_type)
runtimes_by_platform[platform].each do |runtime|
output, ec = simctl("create '#{device_type['name']}' '#{device_type['identifier']}' '#{runtime['identifier']}' 2>&1")
if ec == 0
if firstOnly
# We only want to create a single simulator for each device type so
# skip the rest.
runtimes_by_platform[platform] = []
break
else
next
end
end
# Not all runtime and device pairs are valid as newer simulator runtimes
# don't support older devices. The exact error code for this changes
# every few versions of Xcode, so this just lists all the ones we've
# seen.
next if /domain=com.apple.CoreSimulator.SimError, code=(?<code>\d+)/ =~ output and [161, 162, 163, 403].include? code.to_i
puts "Failed to create device of type #{device_type['identifier']} with runtime #{runtime['identifier']}:"
output.each_line do |line|
puts " #{line}"
end
end
end
puts ' done!'
if firstOnly
exit 0
end
if prelaunch_simulator.include? 'tvos'
print 'Booting Apple TV simulator...'
system("xcrun simctl boot 'Apple TV'") or raise "Failed to boot Apple TV simulator"
else
print 'Booting iPhone 8 simulator...'
system("xcrun simctl boot 'iPhone 8'") or raise "Failed to boot iPhone 8 simulator"
end
puts ' done!'
print 'Waiting for dyld shared cache to update...'
while system('pgrep -q update_dyld_sim_shared_cache')
sleep 15
end
puts ' done!'
rescue => e
if (attempts += 1) < 5
puts ''
puts e.message
e.backtrace.each { |line| puts line }
puts ''
puts 'Retrying...'
retry
end
system('ps auxwww')
system('xcrun simctl list')
raise
end