aboutsummaryrefslogtreecommitdiff
path: root/release/src/cargo.rs
diff options
context:
space:
mode:
Diffstat (limited to 'release/src/cargo.rs')
-rw-r--r--release/src/cargo.rs220
1 files changed, 0 insertions, 220 deletions
diff --git a/release/src/cargo.rs b/release/src/cargo.rs
deleted file mode 100644
index c1ed4118f..000000000
--- a/release/src/cargo.rs
+++ /dev/null
@@ -1,220 +0,0 @@
1//! Tools for working with Cargo.
2
3use std::ffi::OsStr;
4use std::path::{Path, PathBuf};
5use std::process::{Command, Stdio};
6
7use anyhow::{bail, Result};
8use serde::{Deserialize, Serialize};
9
10use crate::windows_safe_path;
11
12#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
13pub struct Artifact {
14 pub executable: PathBuf,
15}
16
17/// Execute cargo with the given arguments and from the specified directory.
18pub fn run(args: &[String], cwd: &Path) -> Result<()> {
19 run_with_env::<[(&str, &str); 0], _, _>(args, cwd, [], false)?;
20 Ok(())
21}
22
23/// Execute cargo with the given arguments and from the specified directory.
24pub fn run_with_env<I, K, V>(args: &[String], cwd: &Path, envs: I, capture: bool) -> Result<String>
25where
26 I: IntoIterator<Item = (K, V)> + core::fmt::Debug,
27 K: AsRef<OsStr>,
28 V: AsRef<OsStr>,
29{
30 if !cwd.is_dir() {
31 bail!("The `cwd` argument MUST be a directory");
32 }
33
34 // Make sure to not use a UNC as CWD!
35 // That would make `OUT_DIR` a UNC which will trigger things like the one fixed in https://github.com/dtolnay/rustversion/pull/51
36 // While it's fixed in `rustversion` it's not fixed for other crates we are
37 // using now or in future!
38 let cwd = windows_safe_path(cwd);
39
40 println!(
41 "Running `cargo {}` in {:?} - Environment {:?}",
42 args.join(" "),
43 cwd,
44 envs
45 );
46
47 let mut command = Command::new(get_cargo());
48
49 command
50 .args(args)
51 .current_dir(cwd)
52 .envs(envs)
53 .stdout(if capture { Stdio::piped() } else { Stdio::inherit() })
54 .stderr(if capture { Stdio::piped() } else { Stdio::inherit() });
55
56 if args.iter().any(|a| a.starts_with('+')) {
57 // Make sure the right cargo runs
58 command.env_remove("CARGO");
59 }
60
61 let output = command.stdin(Stdio::inherit()).output()?;
62
63 // Make sure that we return an appropriate exit code here, as Github Actions
64 // requires this in order to function correctly:
65 if output.status.success() {
66 Ok(String::from_utf8_lossy(&output.stdout).to_string())
67 } else {
68 bail!("Failed to execute cargo subcommand `cargo {}`", args.join(" "),)
69 }
70}
71
72fn get_cargo() -> String {
73 // On Windows when executed via `cargo run` (e.g. via the xtask alias) the
74 // `cargo` on the search path is NOT the cargo-wrapper but the `cargo` from the
75 // toolchain - that one doesn't understand `+toolchain`
76 #[cfg(target_os = "windows")]
77 let cargo = if let Ok(cargo) = std::env::var("CARGO_HOME") {
78 format!("{cargo}/bin/cargo")
79 } else {
80 String::from("cargo")
81 };
82
83 #[cfg(not(target_os = "windows"))]
84 let cargo = String::from("cargo");
85
86 cargo
87}
88
89#[derive(Debug, Default)]
90pub struct CargoArgsBuilder {
91 toolchain: Option<String>,
92 subcommand: String,
93 target: Option<String>,
94 features: Vec<String>,
95 args: Vec<String>,
96}
97
98impl CargoArgsBuilder {
99 #[must_use]
100 pub fn new() -> Self {
101 Self {
102 toolchain: None,
103 subcommand: String::new(),
104 target: None,
105 features: vec![],
106 args: vec![],
107 }
108 }
109
110 #[must_use]
111 pub fn toolchain<S>(mut self, toolchain: S) -> Self
112 where
113 S: Into<String>,
114 {
115 self.toolchain = Some(toolchain.into());
116 self
117 }
118
119 #[must_use]
120 pub fn subcommand<S>(mut self, subcommand: S) -> Self
121 where
122 S: Into<String>,
123 {
124 self.subcommand = subcommand.into();
125 self
126 }
127
128 #[must_use]
129 pub fn target<S>(mut self, target: S) -> Self
130 where
131 S: Into<String>,
132 {
133 self.target = Some(target.into());
134 self
135 }
136
137 #[must_use]
138 pub fn features(mut self, features: &[String]) -> Self {
139 self.features = features.to_vec();
140 self
141 }
142
143 #[must_use]
144 pub fn artifact_dir<S>(mut self, artifact_dir: S) -> Self
145 where
146 S: Into<String>,
147 {
148 self.args.push(format!("--artifact-dir={}", artifact_dir.into()));
149 self
150 }
151
152 #[must_use]
153 pub fn arg<S>(mut self, arg: S) -> Self
154 where
155 S: Into<String>,
156 {
157 self.args.push(arg.into());
158 self
159 }
160
161 #[must_use]
162 pub fn build(&self) -> Vec<String> {
163 let mut args = vec![];
164
165 if let Some(ref toolchain) = self.toolchain {
166 args.push(format!("+{toolchain}"));
167 }
168
169 args.push(self.subcommand.clone());
170
171 if let Some(ref target) = self.target {
172 args.push(format!("--target={target}"));
173 }
174
175 if !self.features.is_empty() {
176 args.push(format!("--features={}", self.features.join(",")));
177 }
178
179 for arg in self.args.iter() {
180 args.push(arg.clone());
181 }
182
183 args
184 }
185}
186
187#[derive(Debug, Default)]
188pub struct CargoBatchBuilder {
189 commands: Vec<Vec<String>>,
190}
191
192impl CargoBatchBuilder {
193 #[must_use]
194 pub fn new() -> Self {
195 Self { commands: vec![] }
196 }
197
198 #[must_use]
199 pub fn command(mut self, args: Vec<String>) -> Self {
200 self.commands.push(args);
201 self
202 }
203
204 pub fn add_command(&mut self, args: Vec<String>) -> &mut Self {
205 self.commands.push(args);
206 self
207 }
208
209 #[must_use]
210 pub fn build(&self) -> Vec<String> {
211 let mut args = vec!["batch".to_string()];
212
213 for command in &self.commands {
214 args.push("---".to_string());
215 args.extend(command.clone());
216 }
217
218 args
219 }
220}