creator_tools/error.rs
1//! Contains `Error`, `AndroidError`, `AppleError` types used by `creator-tools`.
2
3use apple_bundle::plist;
4use displaydoc::Display;
5use std::path::PathBuf;
6use std::process::Command;
7use thiserror::Error;
8
9/// `Result` type that used in `creator-tools`.
10pub type Result<T> = std::result::Result<T, Error>;
11
12/// Android specific error type
13#[derive(Display, Debug, Error)]
14pub enum AndroidError {
15 /// Android SDK is not found
16 AndroidSdkNotFound,
17 /// Android NDK is not found
18 AndroidNdkNotFound,
19 /// Android SDK has no build tools
20 BuildToolsNotFound,
21 /// Android SDK has no platforms installed
22 NoPlatformsFound,
23 /// Platform {0} is not installed
24 PlatformNotFound(u32),
25 /// Target is not supported
26 UnsupportedTarget,
27 /// Host {0} is not supported
28 UnsupportedHost(String),
29 /// Invalid semver
30 InvalidSemver,
31 /// Unsupported or invalid target: {0}
32 InvalidBuildTarget(String),
33 /// Failed to find AndroidManifest.xml in path: {0}
34 FailedToFindAndroidManifest(String),
35 /// AndroidManifest error
36 AndroidManifest(#[from] android_manifest::error::Error),
37}
38
39/// Apple specific error type.
40#[derive(Display, Debug, Error)]
41pub enum AppleError {
42 /// Code signing profile not found
43 CodeSigningProfilesNotFound,
44 /// Code signing profile not provided
45 CodeSigningProfileNotProvided,
46 /// Codesign failed {0}
47 CodesignFailed(String),
48 /// Failed to archive payload
49 ZipCommandFailed,
50 /// Codesign allocate not found
51 CodesignAllocateNotFound,
52 /// Simctl error
53 Simctl(simctl::Error),
54 /// Target dir does not exists
55 TargetNotFound,
56 /// Resources dir does not exists
57 ResourcesNotFound,
58 /// Assets dir does not exists
59 AssetsNotFound,
60 /// Failed to find Info.plist in path: {0}
61 FailedToFindInfoPlist(String),
62 /// Plist data error
63 Plist(#[from] plist::Error),
64}
65
66/// Main error type.
67#[derive(Display, Debug, Error)]
68pub enum Error {
69 /// Command '{0:?}' had a non-zero exit code. Stdout: {1} Stderr: {2}
70 CmdFailed(Command, String, String),
71 /// Command {0} not found
72 CmdNotFound(String),
73 /// Invalid profile: {0}
74 InvalidProfile(String),
75 /// Invalid interface orientation: {0:?}
76 InvalidInterfaceOrientation(String),
77 /// GNU toolchain binary `{gnu_bin}` nor LLVM toolchain binary `{llvm_bin}` found in
78 /// `{toolchain_path:?}`
79 ToolchainBinaryNotFound {
80 toolchain_path: PathBuf,
81 gnu_bin: String,
82 llvm_bin: String,
83 },
84 /// Path {0:?} doesn't exist
85 PathNotFound(PathBuf),
86 /// Failed to find cargo manifest: {0}
87 FailedToFindCargoManifest(String),
88 /// Failed to choose shell string color.
89 /// Argument for --color must be auto, always, or never, but found `{}`
90 FailedToChooseShellStringColor(String),
91 /// IO error
92 Io(#[from] std::io::Error),
93 /// FS Extra error
94 FsExtra(#[from] fs_extra::error::Error),
95 /// Android error
96 Android(#[from] AndroidError),
97 /// Apple error
98 Apple(#[from] AppleError),
99 /// Other error
100 OtherError(#[from] Box<dyn std::error::Error>),
101}
102
103/// Extension trait for [`Command`] that helps
104/// to wrap output and print logs from command execution.
105///
106/// [`Command`]: std::process::Command
107pub trait CommandExt {
108 /// Executes the command as a child process, then captures an output and return it.
109 /// If command termination wasn't successful wraps an output into error and return it.
110 fn output_err(self, print_logs: bool) -> Result<std::process::Output>;
111}
112
113impl CommandExt for Command {
114 fn output_err(mut self, print_logs: bool) -> Result<std::process::Output> {
115 // Enables log print during command execution
116 let output = match print_logs {
117 true => self.spawn().and_then(|p| p.wait_with_output())?,
118 false => self.output()?,
119 };
120 if !output.status.success() {
121 return Err(Error::CmdFailed(
122 self,
123 String::from_utf8_lossy(&output.stdout).to_string(),
124 String::from_utf8_lossy(&output.stderr).to_string(),
125 ));
126 }
127 Ok(output)
128 }
129}
130
131impl From<plist::Error> for Error {
132 fn from(error: plist::Error) -> Self {
133 AppleError::from(error).into()
134 }
135}
136
137impl From<simctl::Error> for Error {
138 fn from(error: simctl::Error) -> Self {
139 AppleError::Simctl(error).into()
140 }
141}