mz_testdrive/action/
protobuf.rs
1use 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 for path in inputs.iter().chain(iter::once(&output)) {
31 if path.contains(path::MAIN_SEPARATOR) {
32 bail!("separators in paths are forbidden");
34 }
35 }
36 let protoc = match env::var_os("PROTOC") {
37 None => mz_build_tools::protoc(),
38 Some(protoc) => PathBuf::from(protoc),
39 };
40 let protoc_include = match env::var_os("PROTOC_INCLUDE") {
41 None => mz_build_tools::protoc_include(),
42 Some(include) => PathBuf::from(include),
43 };
44 let output_path = state.temp_path.join(&output);
45 let status = Command::new(protoc)
46 .arg("--include_imports")
47 .arg("-I")
48 .arg(&state.temp_path)
49 .arg("-I")
50 .arg(&protoc_include)
51 .arg("--descriptor_set_out")
52 .arg(state.temp_path.join(&output).clone())
53 .args(&inputs)
54 .status()
55 .await
56 .context("invoking protoc failed")?;
57 if !status.success() {
58 bail!("protoc exited unsuccessfully");
59 }
60 if let Some(var) = cmd.args.opt_string("set-var") {
61 let res = std::fs::read(output_path)?;
62 let hex_encoded = hex::encode(res);
63 state.cmd_vars.insert(var, format!("\\x{hex_encoded}"));
64 }
65 Ok(ControlFlow::Continue)
66}