mz_testdrive/action/
protobuf.rs1use std::path::{self, PathBuf};
11use std::{env, iter};
12
13use anyhow::{Context, bail};
14use tokio::process::Command;
15
16use crate::action::{ControlFlow, State};
17use crate::parser::BuiltinCommand;
18
19pub async fn run_compile_descriptors(
20 mut cmd: BuiltinCommand,
21 state: &mut State,
22) -> Result<ControlFlow, anyhow::Error> {
23 let inputs: Vec<String> = cmd
24 .args
25 .string("inputs")?
26 .split(',')
27 .map(|s| s.into())
28 .collect();
29 let output = cmd.args.string("output")?;
30 let set_var = cmd.args.opt_string("set-var");
31 cmd.args.done()?;
32 for path in inputs.iter().chain(iter::once(&output)) {
33 if path.contains(path::MAIN_SEPARATOR) {
34 bail!("separators in paths are forbidden");
36 }
37 }
38 let protoc = match env::var_os("PROTOC") {
39 None => mz_build_tools::protoc(),
40 Some(protoc) => PathBuf::from(protoc),
41 };
42 let protoc_include = match env::var_os("PROTOC_INCLUDE") {
43 None => mz_build_tools::protoc_include(),
44 Some(include) => PathBuf::from(include),
45 };
46 let output_path = state.temp_path.join(&output);
47 let status = Command::new(protoc)
48 .arg("--include_imports")
49 .arg("-I")
50 .arg(&state.temp_path)
51 .arg("-I")
52 .arg(&protoc_include)
53 .arg("--descriptor_set_out")
54 .arg(state.temp_path.join(&output).clone())
55 .args(&inputs)
56 .status()
57 .await
58 .context("invoking protoc failed")?;
59 if !status.success() {
60 bail!("protoc exited unsuccessfully");
61 }
62 if let Some(var) = set_var {
63 let res = std::fs::read(output_path)?;
64 let hex_encoded = hex::encode(res);
65 state.cmd_vars.insert(var, format!("\\x{hex_encoded}"));
66 }
67 Ok(ControlFlow::Continue)
68}