creator_simctl/
simctl.rs

1use std::path::{Path, PathBuf};
2use std::process::{Command, Stdio};
3
4use super::{Result, Validate};
5
6/// Wrapper around the `simctl` utility.
7#[derive(Clone, Debug)]
8pub struct Simctl {
9    developer_dir: PathBuf,
10}
11
12impl Simctl {
13    /// Returns a new instance of the Rust wrapper around the `simctl` utility.
14    pub fn new() -> Simctl {
15        if let Some(developer_dir) = std::env::var_os("DEVELOPER_DIR") {
16            Simctl::with_developer_dir(&Path::new(&developer_dir))
17        } else {
18            let output = Command::new("xcode-select")
19                .arg("--print-path")
20                .stdout(Stdio::piped())
21                .output()
22                .unwrap();
23
24            let output = String::from_utf8(output.stdout).unwrap();
25            let path = Path::new(output.trim());
26
27            Simctl::with_developer_dir(path)
28        }
29    }
30
31    /// Returns a new wrapper around the `simctl` utility with the given
32    /// developer dir. Use this function if Xcode is not installed in the
33    /// default path or if you want to distinguish between multiple
34    /// installations of Xcode (e.g. stable and beta).
35    pub fn with_developer_dir(path: &Path) -> Simctl {
36        Simctl {
37            developer_dir: path.to_path_buf(),
38        }
39    }
40
41    /// Returns a new wrapper around the `simctl` utility with the given Xcode
42    /// path. Use this function if Xcode is not installed in the default path or
43    /// if you want to distinguish between multiple installations of Xcode (e.g.
44    /// stable and beta).
45    pub fn with_xcode(path: &Path) -> Simctl {
46        Simctl::with_xcode(&path.join("Contents/Developer"))
47    }
48
49    /// Returns a new command that will invoke the `simctl` binary with the
50    /// given subcommand.
51    pub fn command(&self, name: &str) -> Command {
52        let mut command = Command::new(self.developer_dir.join("usr/bin/simctl"));
53        command.arg(name);
54        command.stdout(Stdio::piped());
55        command.stderr(Stdio::piped());
56        command
57    }
58
59    /// Opens the Simulator.app that corresponds to this instance of `simctl`
60    /// (in case of multiple Xcode installations).
61    pub fn open(&self) -> Result<()> {
62        Command::new("open")
63            .arg(
64                self.developer_dir
65                    .join("Applications")
66                    .join("Simulator.app"),
67            )
68            .stdout(Stdio::null())
69            .stderr(Stdio::null())
70            .output()?
71            .validate()
72    }
73}