Skip to content

Commit

Permalink
Merge pull request fastlane#3627 from matthewellis/master
Browse files Browse the repository at this point in the history
Add support for connected devices
  • Loading branch information
mfurtak committed Apr 22, 2016
2 parents 22d739a + 65e151a commit 467662a
Show file tree
Hide file tree
Showing 6 changed files with 686 additions and 25 deletions.
2 changes: 1 addition & 1 deletion fastlane_core/lib/fastlane_core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
require 'fastlane_core/ipa_upload_package_builder'
require 'fastlane_core/print_table'
require 'fastlane_core/project'
require 'fastlane_core/simulator'
require 'fastlane_core/device_manager'
require 'fastlane_core/crash_reporting/crash_reporting'
require 'fastlane_core/ui/ui'

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
require 'open3'
require 'plist'

module FastlaneCore
class Simulator
class DeviceManager
class << self
def requested_os_type
'iOS'
def all(requested_os_type = "")
return connected_devices(requested_os_type) + simulators(requested_os_type)
end

def all
UI.message("Fetching available devices") if $verbose
def simulators(requested_os_type = "")
UI.message("Fetching available simulator devices") if $verbose

@devices = []
os_type = 'unknown'
Expand All @@ -31,29 +32,65 @@ def all
# iPad 2 (0EDE6AFC-3767-425A-9658-AAA30A60F212) (Shutdown)
# iPad Air 2 (4F3B8059-03FD-4D72-99C0-6E9BBEE2A9CE) (Shutdown) (unavailable, device type profile not found)
match = line.match(/\s+([^\(]+) \(([-0-9A-F]+)\) \(([^\(]+)\)(.*unavailable.*)?/)
if match && !match[4] && os_type == requested_os_type
@devices << Device.new(name: match[1], os_version: os_version, udid: match[2], state: match[3])
if match && !match[4] && (os_type == requested_os_type || requested_os_type == "")
@devices << Device.new(name: match[1], os_version: os_version, udid: match[2], state: match[3], is_simulator: true)
end
end
end

return @devices
end

def clear_cache
@devices = nil
end
def connected_devices(requested_os_type)
Helper.log.info "Fetching available connected devices" if $verbose

# Reset all simulators of this type
def reset_all
all.each(&:reset)
end
device_types = if requested_os_type == "tvOS"
["AppleTV"]
elsif requested_os_type == "iOS"
["iPhone", "iPad", "iPod"]
else
[]
end

# Reset simulator by UDID or name and OS version
# Latter is useful when combined with -destination option of xcodebuild
def reset(udid: nil, name: nil, os_version: nil)
match = all.detect { |device| device.udid == udid || device.name == name && device.os_version == os_version }
match.reset if match
devices = [] # Return early if no supported devices are being searched for
if device_types.count == 0
return devices
end

usb_devices_output = ''
Open3.popen3("system_profiler SPUSBDataType -xml") do |stdin, stdout, stderr, wait_thr|
usb_devices_output = stdout.read
end

device_uuids = []
result = Plist.parse_xml(usb_devices_output)
result[0]['_items'].each do |host_controller| # loop just incase the host system has more then 1 controller
host_controller['_items'].each do |usb_device|
is_supported_device = device_types.any? { |device_type| usb_device['_name'] == device_type }
if is_supported_device && usb_device['serial_num'].length == 40
device_uuids.push(usb_device['serial_num'])
end
end
end

if device_uuids.count > 0 # instruments takes a little while to return so skip it if we have no devices
instruments_devices_output = ''
Open3.popen3("instruments -s devices") do |stdin, stdout, stderr, wait_thr|
instruments_devices_output = stdout.read
end

instruments_devices_output.split(/\n/).each do |instruments_device|
device_uuids.each do |device_uuid|
match = instruments_device.match(/(.+) \(([0-9.]+)\) \[([0-9a-f]+)\]?/)
if match && match[3] == device_uuid
devices << Device.new(name: match[1], udid: match[3], os_version: match[2], state: "Booted", is_simulator: false)
Helper.log.info "USB Device Found - \"" + match[1] + "\" (" + match[2] + ") UUID:" + match[3] if $verbose
end
end
end
end

return devices
end

# The code below works from Xcode 7 on
Expand Down Expand Up @@ -104,13 +141,15 @@ class Device
attr_accessor :os_version
attr_accessor :ios_version # Preserved for backwards compatibility
attr_accessor :state
attr_accessor :is_simulator

def initialize(name: nil, udid: nil, os_version: nil, state: nil)
def initialize(name: nil, udid: nil, os_version: nil, state: nil, is_simulator: nil)
self.name = name
self.udid = udid
self.os_version = os_version
self.ios_version = os_version
self.state = state
self.is_simulator = is_simulator
end

def to_s
Expand All @@ -126,18 +165,42 @@ def reset
end
end

class Simulator
class << self
def all
return DeviceManager.simulators('iOS')
end

# Reset all simulators of this type
def reset_all
all.each(&:reset)
end

# Reset simulator by UDID or name and OS version
# Latter is useful when combined with -destination option of xcodebuild
def reset(udid: nil, name: nil, os_version: nil)
match = all.detect { |device| device.udid == udid || device.name == name && device.os_version == os_version }
match.reset if match
end

def clear_cache
@devices = nil
end
end
end

class SimulatorTV < Simulator
class << self
def requested_os_type
'tvOS'
def all
return DeviceManager.simulators('tvOS')
end
end
end

class SimulatorWatch < Simulator
class << self
def requested_os_type
'watchOS'
def all
return DeviceManager.simulators('watchOS')
end
end
end
Expand Down
Loading

0 comments on commit 467662a

Please sign in to comment.