apple_clis/cli/
device_name.rs1use crate::prelude::*;
2use crate::xcrun::simctl::XcRunSimctlInstance;
3
4#[derive(clap::Args, Debug)]
5#[group(required = true, multiple = false)]
6pub struct DeviceSimulatorUnBootedArgs {
7 #[arg(long, group = "device_name")]
9 ipad: bool,
10
11 #[arg(long, group = "device_name")]
13 iphone: bool,
14
15 #[arg(group = "device_name")]
17 name: Option<DeviceName>,
18}
19
20#[derive(clap::Args, Debug)]
21#[group(required = true)]
22pub struct DeviceSimulatorBootedArgs {
23 #[arg(long, group = "device_name")]
26 booted: bool,
27
28 #[arg(long, requires = "device_name")]
30 auto_boot: bool,
31
32 #[arg(long, group = "device_name")]
34 ipad: bool,
35
36 #[arg(long, group = "device_name")]
38 iphone: bool,
39
40 #[arg(group = "device_name")]
43 name: Option<DeviceName>,
44}
45
46impl DeviceSimulatorUnBootedArgs {
47 pub fn resolve(self, simctl_instance: &XcRunSimctlInstance) -> color_eyre::Result<DeviceName> {
48 match (self.ipad, self.iphone, self.name) {
49 (false, false, Some(name)) => Ok(name),
50 (true, false, None) => {
51 let list = simctl_instance.list()?;
52 let latest_ipad = list
53 .get_success_reported()?
54 .devices()
55 .names()
56 .ipads()
57 .max()
58 .ok_or_else(|| eyre!("No simulator iPads found!"))?;
59 Ok((*latest_ipad).into())
60 }
61 (false, true, None) => {
62 let list_output = &simctl_instance.list()?;
63 let latest_iphone = list_output
64 .get_success_reported()?
65 .devices()
66 .names()
67 .iphones()
68 .max()
69 .ok_or_else(|| eyre!("No simulator iPhones found!"))?;
70 Ok((*latest_iphone).into())
71 }
72 _ => Err(eyre!("Clap arguments should prevent this")),
73 }
74 }
75}
76
77impl DeviceSimulatorBootedArgs {
78 pub fn resolve(self, simctl_instance: &XcRunSimctlInstance) -> color_eyre::Result<DeviceName> {
79 let list = simctl_instance.list()?;
80 let booted_devices = list
81 .get_success_reported()?
82 .devices()
83 .filter(|d| d.ready())
84 .collect::<Vec<_>>();
85 if booted_devices.is_empty() && !self.auto_boot {
86 Err(
87 eyre!("No booted devices found!")
88 .with_suggestion(|| "try using the flag --auto-boot")
89 .with_suggestion(|| "try running `apple-clis xcrun simctl boot` to boot a simulator"),
90 )
91 } else {
92 match (
93 self.booted,
94 self.ipad,
95 self.iphone,
96 self.name,
97 self.auto_boot,
98 ) {
99 (true, false, false, None, auto_boot) => {
100 if auto_boot {
101 let a_device_name = &list
102 .get_success_reported()?
103 .devices()
104 .a_device()
105 .ok_or_else(|| eyre!("Couldn't find any simulators installed"))?
106 .name;
107 info!(device_name = %a_device_name, "Since auto-boot is enabled, booting a simulator");
108 simctl_instance.boot(a_device_name)?.success()?;
109 Ok(a_device_name.clone())
110 } else {
111 Ok(booted_devices[0].name.clone())
112 }
113 }
114 (false, true, false, None, auto_boot) => {
115 if !auto_boot {
116 booted_devices
117 .iter()
118 .filter_map(|d| d.name.get_ipad())
119 .max()
120 .cloned()
121 .map(DeviceName::from)
122 .ok_or_else(|| eyre!("No booted iPads found!"))
123 .with_suggestion(|| {
124 "try running `apple-clis xcrun simctl boot --ipad` to boot a simulator"
125 })
126 .with_note(|| format!("Booted devices: {:?}", &booted_devices))
127 } else {
128 let a_device_name = (*list
129 .get_success_reported()?
130 .devices()
131 .names()
132 .an_ipad()
133 .ok_or_else(|| eyre!("Couldn't find any iPad simulators installed"))?)
134 .into();
135 info!(device_name = %a_device_name, "Since auto-boot is enabled, booting an iPad simulator");
136 simctl_instance.boot(&a_device_name)?.success()?;
137 Ok(a_device_name)
138 }
139 }
140 (false, false, true, None, auto_boot) => {
141 if !auto_boot {
142 booted_devices
143 .iter()
144 .filter_map(|d| d.name.get_iphone())
145 .max()
146 .cloned()
147 .map(DeviceName::from)
148 .ok_or_else(|| {
149 eyre!("No booted iPhones found!")
150 .with_suggestion(|| {
151 "try running `apple-clis xcrun simctl boot --iphone` to boot a simulator"
152 })
153 .with_note(|| format!("Booted devices: {:?}", &booted_devices))
154 })
155 } else {
156 let a_device_name: DeviceName = (*list
157 .get_success_reported()?
158 .devices()
159 .names()
160 .an_iphone()
161 .ok_or_else(|| eyre!("Couldn't find any iPhone simulators installed"))?)
162 .into();
163 info!(device_name = %a_device_name, "Since auto-boot is enabled, booting an iPhone simulator");
164 simctl_instance.boot(&a_device_name)?.success()?;
165 Ok(a_device_name)
166 }
167 }
168 (false, false, false, Some(name), auto_boot) => {
169 let output = list.get_success_reported()?;
170 let devices = output.devices().names().collect::<Vec<_>>();
171 if !devices.iter().any(|n| n == &&name) {
172 Err(
173 eyre!("The provided device name is not installed")
174 .with_suggestion(|| {
175 format!(
176 "try running `apple-clis xcrun simctl boot --name {}` to boot a simulator",
177 name
178 )
179 })
180 .with_suggestion(|| {
181 "try running `apple-clis xcrun simctl list` to see installed simulators"
182 })
183 .with_note(|| format!("Installed devices: {:?}", &devices)),
184 )
185 } else if auto_boot {
186 simctl_instance.boot(&name)?.success()?;
187 Ok(name)
188 } else {
189 Ok(name)
190 }
191 }
192 _ => Err(eyre!("Clap arguments should prevent this")),
193 }
194 }
195 }
196}