mz_testdrive/action/
protobuf.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10use 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            // The goal isn't security, but preventing mistakes.
33            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}