Skip to content

Commit 3385401

Browse files
committed
Fix cargo and binary args order bug in run_process_for_workspace
1 parent 01de338 commit 3385401

File tree

1 file changed

+86
-5
lines changed

1 file changed

+86
-5
lines changed

crates/tracel-xtask/src/utils/process.rs

Lines changed: 86 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ pub fn run_process(
5050
#[allow(clippy::too_many_arguments)]
5151
pub fn run_process_for_workspace<'a>(
5252
name: &str,
53-
mut args: Vec<&'a str>,
53+
args: Vec<&'a str>,
5454
excluded: &'a [String],
5555
group_regexp: Option<&str>,
5656
group_name: Option<&str>,
@@ -59,21 +59,26 @@ pub fn run_process_for_workspace<'a>(
5959
ignore_msg: Option<&str>,
6060
) -> anyhow::Result<()> {
6161
let group_rx: Option<Regex> = group_regexp.map(|r| Regex::new(r).unwrap());
62+
// split the args between cargo args and binary args so that we can extend the cargo args
63+
// and then append the binary args back.
64+
let (cargo_args, binary_args) = split_vector(&args, "--");
65+
let mut cmd_args = cargo_args.to_owned();
6266
excluded
6367
.iter()
64-
.for_each(|ex| args.extend(["--exclude", ex]));
65-
group_info!("Command line: cargo {}", args.join(" "));
68+
.for_each(|ex| cmd_args.extend(["--exclude", ex]));
69+
cmd_args.extend(binary_args);
70+
group_info!("Command line: cargo {}", cmd_args.join(" "));
6671
// process
6772
let mut child = Command::new(name)
68-
.args(&args)
73+
.args(&cmd_args)
6974
.stdout(Stdio::piped())
7075
.stderr(Stdio::piped())
7176
.spawn()
7277
.map_err(|e| {
7378
anyhow::anyhow!(format!(
7479
"Failed to start {} {}: {}",
7580
name,
76-
args.first().unwrap(),
81+
cmd_args.first().unwrap(),
7782
e
7883
))
7984
})?;
@@ -209,3 +214,79 @@ fn remove_ansi_codes(s: &str) -> String {
209214
fn standardize_slashes(s: &str) -> String {
210215
s.replace('\\', "/")
211216
}
217+
218+
/// Split given VEC into a left and right vectors where SPLIT belongs to the right vector.
219+
/// If SPLIT does not exist in VEC then left is a VEC slice and right is empty.
220+
fn split_vector<T: PartialEq>(vec: &[T], split: T) -> (&[T], &[T]) {
221+
let mut left = vec;
222+
let mut right = &vec[vec.len()..];
223+
if let Some(pos) = vec.iter().position(|e| *e == split) {
224+
left = &vec[..pos];
225+
right = &vec[pos..];
226+
}
227+
(left, right)
228+
}
229+
230+
#[cfg(test)]
231+
mod tests {
232+
use super::*;
233+
use rstest::rstest;
234+
235+
#[rstest]
236+
fn test_random_port_in_range() {
237+
for _ in 0..10000 {
238+
let port = random_port();
239+
assert!(
240+
port >= 3000 && port <= 9999,
241+
"Port should be between 3000 and 9999, got {}",
242+
port
243+
);
244+
}
245+
}
246+
247+
#[rstest]
248+
#[case::simple_escape_code("\x1b[31mRed Text\x1b[0m", "Red Text")]
249+
#[case::complex_escape_code("\x1b[1;34mBold Blue Text\x1b[0m", "Bold Blue Text")]
250+
#[case::no_escape_code("No ANSI Codes", "No ANSI Codes")]
251+
fn test_remove_ansi_codes(#[case] input: &str, #[case] expected: &str) {
252+
let result = remove_ansi_codes(input);
253+
assert_eq!(
254+
result, expected,
255+
"Expected '{}', but got '{}'",
256+
expected, result
257+
);
258+
}
259+
260+
#[rstest]
261+
#[case::windows_path(r"C:\path\to\file", "C:/path/to/file")]
262+
#[case::network_path(r"\\network\share\file", "//network/share/file")]
263+
#[case::already_standard_path("/already/standard/path", "/already/standard/path")]
264+
fn test_standardize_slashes(#[case] input: &str, #[case] expected: &str) {
265+
let result = standardize_slashes(input);
266+
assert_eq!(
267+
result, expected,
268+
"Expected '{}', but got '{}'",
269+
expected, result
270+
);
271+
}
272+
273+
#[rstest]
274+
#[case::element_found(vec!["a", "b", "c", "d", "e", "f"], "d", vec!["a", "b", "c"], vec!["d", "e", "f"])]
275+
#[case::element_not_found(vec!["a", "b", "c", "d", "e", "f"], "z", vec!["a", "b", "c", "d", "e", "f"], vec![])]
276+
#[case::element_at_start(vec!["a", "b", "c", "d", "e", "f"], "a", vec![], vec!["a", "b", "c", "d", "e", "f"])]
277+
#[case::element_at_end(vec!["a", "b", "c", "d", "e", "f"], "f", vec!["a", "b", "c", "d", "e"], vec!["f"])]
278+
#[case::empty_vector(vec![], "x", vec![], vec![])]
279+
#[case::cargo_with_binary_args(vec!["cargo", "build", "--exclude", "crate", "--workpspace", "--", "--color", "always"], "--", vec!["cargo", "build", "--exclude", "crate", "--workpspace"], vec!["--", "--color", "always"])]
280+
#[case::cargo_without_binary_args(vec!["cargo", "build", "--exclude", "crate", "--workpspace"], "--", vec!["cargo", "build", "--exclude", "crate", "--workpspace"], vec![])]
281+
fn test_split_vector(
282+
#[case] vec: Vec<&str>,
283+
#[case] split_elem: &str,
284+
#[case] expected_left: Vec<&str>,
285+
#[case] expected_right: Vec<&str>,
286+
) {
287+
let (left, right) = split_vector(&vec, split_elem);
288+
289+
assert_eq!(left, &expected_left);
290+
assert_eq!(right, &expected_right);
291+
}
292+
}

0 commit comments

Comments
 (0)