use std::path::{Path, PathBuf};
use anyhow::{Context, Result};
pub fn build_venus_workflow(project_path: &Path, output_dir: &Path) -> Result<()> {
println!("🔧 Building Venus workflow...");
super::validate_program_path(project_path)?;
println!(" Step 1: Looking for WIT file...");
let wit_file = find_wit_file(project_path)?;
println!(" ✅ Found WIT: {}", wit_file.display());
println!(" Step 2: Copying WIT to output...");
let output_wit = copy_wit_to_output(&wit_file, output_dir)?;
println!(" ✅ Copied WIT to: {}", output_wit.display());
println!("✅ Venus workflow build complete");
Ok(())
}
fn find_wit_file(project_path: &Path) -> Result<PathBuf> {
let wit_dir = project_path.join("wit");
if wit_dir.is_dir() {
for entry in std::fs::read_dir(&wit_dir)? {
let entry = entry?;
let path = entry.path();
if path.extension().and_then(|s| s.to_str()) == Some("wit") {
return Ok(path);
}
}
}
let interface_wit = project_path.join("interface.wit");
if interface_wit.exists() && interface_wit.is_file() {
return Ok(interface_wit);
}
let target_wit_dir = project_path.join("target/wit");
if target_wit_dir.is_dir() {
for entry in std::fs::read_dir(&target_wit_dir)? {
let entry = entry?;
let path = entry.path();
if path.extension().and_then(|s| s.to_str()) == Some("wit") {
return Ok(path);
}
}
}
anyhow::bail!(
"No WIT file found in {}. Venus macro may not have generated it.\n\
Ensure your workflow uses the rialo! macro and runs `cargo build` first.",
project_path.display()
)
}
fn copy_wit_to_output(wit_file: &Path, output_dir: &Path) -> Result<PathBuf> {
std::fs::create_dir_all(output_dir).with_context(|| {
format!(
"Failed to create output directory: {}",
output_dir.display()
)
})?;
let wit_filename = wit_file
.file_name()
.ok_or_else(|| anyhow::anyhow!("WIT file has no filename"))?;
let output_wit = output_dir.join(wit_filename);
std::fs::copy(wit_file, &output_wit)
.with_context(|| format!("Failed to copy WIT file to {}", output_wit.display()))?;
Ok(output_wit)
}
pub fn is_venus_workflow(project_path: &Path) -> bool {
let cargo_toml = project_path.join("Cargo.toml");
if cargo_toml.exists() {
if let Ok(contents) = std::fs::read_to_string(&cargo_toml) {
if contents.contains("rialo-venus-proc-macro")
|| contents.contains("rialo_venus_proc_macro")
{
return true;
}
}
}
let wit_dir = project_path.join("wit");
if wit_dir.exists() && wit_dir.is_dir() {
return true;
}
let src_dir = project_path.join("src");
if src_dir.exists() && src_dir.is_dir() {
if let Ok(entries) = std::fs::read_dir(&src_dir) {
for entry in entries.flatten() {
let path = entry.path();
if path.extension().and_then(|s| s.to_str()) == Some("rs") {
if let Ok(contents) = std::fs::read_to_string(&path) {
if contents.contains("rialo!") {
return true;
}
}
}
}
}
}
false
}
#[cfg(test)]
mod tests {
use std::fs;
use tempfile::TempDir;
use super::*;
#[test]
fn test_find_wit_file_in_wit_dir() {
let temp = TempDir::new().unwrap();
let wit_dir = temp.path().join("wit");
fs::create_dir(&wit_dir).unwrap();
let wit_file = wit_dir.join("test.wit");
fs::write(&wit_file, "package test;").unwrap();
let found = find_wit_file(temp.path()).unwrap();
assert_eq!(found, wit_file);
}
#[test]
fn test_find_wit_file_not_found() {
let temp = TempDir::new().unwrap();
let result = find_wit_file(temp.path());
assert!(result.is_err());
}
#[test]
fn test_is_venus_workflow_with_dependency() {
let temp = TempDir::new().unwrap();
let cargo_toml = temp.path().join("Cargo.toml");
fs::write(
&cargo_toml,
"[dependencies]\nrialo-venus-proc-macro = \"0.1\"\n",
)
.unwrap();
assert!(is_venus_workflow(temp.path()));
}
#[test]
fn test_is_venus_workflow_with_wit_dir() {
let temp = TempDir::new().unwrap();
let wit_dir = temp.path().join("wit");
fs::create_dir(&wit_dir).unwrap();
assert!(is_venus_workflow(temp.path()));
}
#[test]
fn test_is_venus_workflow_false() {
let temp = TempDir::new().unwrap();
assert!(!is_venus_workflow(temp.path()));
}
}