Class: EmergeCLI::XcodeDeviceManager

Inherits:
Object
  • Object
show all
Defined in:
lib/utils/xcode_device_manager.rb

Defined Under Namespace

Classes: DeviceType

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(environment: Environment.new) ⇒ XcodeDeviceManager

Returns a new instance of XcodeDeviceManager.



14
15
16
# File 'lib/utils/xcode_device_manager.rb', line 14

def initialize(environment: Environment.new)
  @environment = environment
end

Class Method Details

.get_supported_platforms(ipa_path) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/utils/xcode_device_manager.rb', line 19

def get_supported_platforms(ipa_path)
  return [] unless ipa_path&.end_with?('.ipa')

  Zip::File.open(ipa_path) do |zip_file|
    app_entry = zip_file.glob('**/*.app/').first ||
                zip_file.glob('**/*.app').first ||
                zip_file.find { |entry| entry.name.end_with?('.app/') || entry.name.end_with?('.app') }

    raise 'No .app found in .ipa file' unless app_entry

    app_dir = app_entry.name.end_with?('/') ? app_entry.name.chomp('/') : app_entry.name
    info_plist_path = "#{app_dir}/Info.plist"
    info_plist_entry = zip_file.find_entry(info_plist_path)
    raise 'Info.plist not found in app bundle' unless info_plist_entry

    info_plist_content = info_plist_entry.get_input_stream.read
    plist = CFPropertyList::List.new(data: info_plist_content)
    info_plist = CFPropertyList.native_types(plist.value)

    info_plist['CFBundleSupportedPlatforms'] || []
  end
end

Instance Method Details

#find_device_by_id(device_id) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/utils/xcode_device_manager.rb', line 43

def find_device_by_id(device_id)
  Logger.debug "Looking for device with ID: #{device_id}"
  devices_json = execute_command('xcrun xcdevice list')
  devices_data = JSON.parse(devices_json)

  found_device = devices_data.find { |device| device['identifier'] == device_id }
  raise "No device found with ID: #{device_id}" unless found_device

  device_type = found_device['simulator'] ? 'simulator' : 'physical'
  Logger.info "✅ Found device: #{found_device['name']} " \
              "(#{found_device['identifier']}, #{device_type})"
  if found_device['simulator']
    XcodeSimulator.new(found_device['identifier'])
  else
    XcodePhysicalDevice.new(found_device['identifier'])
  end
end

#find_device_by_type(device_type, ipa_path) ⇒ Object



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
# File 'lib/utils/xcode_device_manager.rb', line 61

def find_device_by_type(device_type, ipa_path)
  case device_type
  when DeviceType::VIRTUAL
    find_and_boot_most_recently_used_simulator
  when DeviceType::PHYSICAL
    find_connected_device
  when DeviceType::ANY
    # Check supported platforms in Info.plist to make intelligent choice
    supported_platforms = self.class.get_supported_platforms(ipa_path)
    Logger.debug "Build supports platforms: #{supported_platforms.join(', ')}"

    if supported_platforms.include?('iPhoneOS')
      device = find_connected_device
      return device if device

      # Only fall back to simulator if it's also supported
      unless supported_platforms.include?('iPhoneSimulator')
        raise 'Build only supports physical devices, but no device is connected'
      end
      Logger.info 'No physical device found, falling back to simulator since build supports both'
      find_and_boot_most_recently_used_simulator

    elsif supported_platforms.include?('iPhoneSimulator')
      find_and_boot_most_recently_used_simulator
    else
      raise "Build doesn't support either physical devices or simulators"
    end
  end
end