1use std::fmt;
2use std::process::exit;
3
4use colored::*;
5use failure::Fail;
6
7use crate::builder::{BuildStatus, Builder};
8use crate::error::*;
9
10pub struct CargoAdapter {
25 env_name: String,
26}
27
28impl CargoAdapter {
29 pub fn with_env_var<S: AsRef<str>>(env_name: S) -> Self {
39 CargoAdapter {
40 env_name: env_name.as_ref().to_string(),
41 }
42 }
43
44 #[allow(clippy::needless_pass_by_value)]
49 pub fn build(&self, builder: Builder) -> ! {
50 if let Err(error) = self.build_inner(&builder) {
51 eprintln!("{}", ErrorLogPrinter::print(error));
52 exit(1);
53 } else {
54 exit(0);
55 }
56 }
57
58 fn build_inner(&self, builder: &Builder) -> Result<()> {
59 match builder.build()? {
60 BuildStatus::Success(output) => {
61 let dependencies = output.dependencies()?;
62
63 println!(
64 "cargo:rustc-env={}={}",
65 self.env_name,
66 output.get_assembly_path().display()
67 );
68
69 for path in dependencies {
70 println!("cargo:rerun-if-changed={}", path.display());
71 }
72 }
73
74 BuildStatus::NotNeeded => {
75 println!("cargo:rustc-env={}=/dev/null", self.env_name);
76 }
77 };
78
79 Ok(())
80 }
81}
82
83pub struct ErrorLogPrinter {
101 error: Box<dyn Fail>,
102 colors: bool,
103}
104
105impl ErrorLogPrinter {
106 pub fn print(error: Error) -> Self {
108 Self {
109 error: Box::new(error),
110 colors: true,
111 }
112 }
113
114 pub fn disable_colors(&mut self) -> &mut Self {
116 self.colors = false;
117 self
118 }
119}
120
121trait StringExt {
122 fn prefix_each_line<T>(self, prefix: T) -> Self
123 where
124 T: ToString;
125}
126
127impl StringExt for String {
128 fn prefix_each_line<T: ToString>(self, prefix: T) -> Self {
129 let owned_prefix = prefix.to_string();
130 let glue = String::from("\n") + &owned_prefix;
131
132 owned_prefix + &self.split('\n').collect::<Vec<_>>().join(&glue)
133 }
134}
135
136impl fmt::Display for ErrorLogPrinter {
137 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
138 control::set_override(self.colors);
139
140 write!(
141 f,
142 "{}",
143 self.error
144 .to_string()
145 .prefix_each_line("[PTX] ".bright_black())
146 )?;
147
148 for next in self.error.iter_causes() {
149 write!(
150 f,
151 "\n{}",
152 String::from("\n caused by:").prefix_each_line("[PTX]".bright_black())
153 )?;
154
155 write!(
156 f,
157 "\n{}",
158 next.to_string().prefix_each_line("[PTX] ".bright_black())
159 )?;
160 }
161
162 control::unset_override();
163 Ok(())
164 }
165}