Skip to content

Commit

Permalink
feat(proto-compiler): check required protoc version before build (#65)
Browse files Browse the repository at this point in the history
* feat(proto-compiler): check required protoc version before build

* test(proto-compiler): test protoc version dependency check

* chore: clippy

* chore: self review

* chore: self-review
  • Loading branch information
lklimek authored Apr 30, 2024
1 parent a848ad6 commit 3048c2e
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 2 deletions.
3 changes: 3 additions & 0 deletions proto-compiler/src/constants.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
//! Tenderdash protobuf implementation
// Requirements
pub const DEP_PROTOC_VERSION: f32 = 25.0;

/// Tenderdash repository URL.
pub const TENDERDASH_REPO: &str = "https://github.com/dashpay/tenderdash";

Expand Down
54 changes: 53 additions & 1 deletion proto-compiler/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ use std::{
fs::{copy, create_dir_all, read_to_string, remove_dir_all, File},
io::Write,
path::{Path, PathBuf},
process::Command,
};

use walkdir::WalkDir;

use crate::constants::{GenerationMode, DEFAULT_TENDERDASH_COMMITISH};
use crate::constants::{GenerationMode, DEFAULT_TENDERDASH_COMMITISH, DEP_PROTOC_VERSION};

/// Check out a specific commitish of the tenderdash repository.
///
Expand Down Expand Up @@ -358,3 +359,54 @@ pub(crate) fn check_state(dir: &Path, commitish: &str) -> bool {
Err(_) => false,
}
}

/// Check if all dependencies are met
pub(crate) fn check_deps() -> Result<(), String> {
dep_protoc(DEP_PROTOC_VERSION).map(|_| ())
}

/// Check if protoc is installed and has the required version
fn dep_protoc(expected_version: f32) -> Result<f32, String> {
let protoc = prost_build::protoc_from_env();

// Run `protoc --version` and capture the output
let output = Command::new(protoc)
.arg("--version")
.output()
.map_err(|e| format!("failed to run: {}", e))?;

// Convert the output to a string
let out = output.stdout;
let version_output = String::from_utf8(out.clone())
.map_err(|e| format!("output {:?} is not utf8 string: {}", out, e))?;

// Extract the version number from string like `libprotoc 25.1`
let version: f32 = version_output
.split_whitespace()
.last()
.unwrap()
.parse()
.map_err(|e| format!("failed to parse protoc version {}: {}", version_output, e))?;

if version < expected_version {
Err(format!(
"protoc version must be {} or higher, but found {}; please upgrade: https://github.com/protocolbuffers/protobuf/releases/",
expected_version, version
))
} else {
Ok(version)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_protoc_dep() {
let expected_versions = vec![(10.1, true), (DEP_PROTOC_VERSION, true), (90.5, false)];
for expect in expected_versions {
assert_eq!(dep_protoc(expect.0).is_ok(), expect.1);
}
}
}
8 changes: 7 additions & 1 deletion proto-compiler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ mod constants;
pub use constants::GenerationMode;
use constants::{CUSTOM_FIELD_ATTRIBUTES, CUSTOM_TYPE_ATTRIBUTES, TENDERDASH_REPO};

use crate::functions::{check_state, save_state};
use crate::functions::{check_deps, check_state, save_state};

/// Import and compile protobuf definitions for Tenderdash.
///
Expand Down Expand Up @@ -54,6 +54,12 @@ pub fn proto_compile(mode: GenerationMode) {

let commitish = tenderdash_commitish();

// ensure dependencies are up to date
if let Err(e) = check_deps() {
eprintln!("[error] => {}", e);
std::process::exit(1);
}

// check if this commitish is already downloaded
let download = std::fs::metadata(tenderdash_dir.join("proto")).is_err()
|| !check_state(&prost_out_dir, &commitish);
Expand Down

0 comments on commit 3048c2e

Please sign in to comment.