use std::fs;
use std::path::PathBuf;
use hydroflow_plus::lang::graph::{partition_graph, HydroflowGraph};
use stageleft::internal::quote;
use trybuild_internals_api::cargo::{self, Metadata};
use trybuild_internals_api::env::Update;
use trybuild_internals_api::run::{PathDependency, Project};
use trybuild_internals_api::{dependencies, features, path, Runner};
pub fn compile_graph_trybuild(graph: HydroflowGraph, extra_stmts: Vec<syn::Stmt>) -> syn::File {
let partitioned_graph = partition_graph(graph).expect("Failed to partition (cycle detected).");
let mut diagnostics = Vec::new();
let tokens =
partitioned_graph.as_code("e! { hydroflow_plus }, true, quote!(), &mut diagnostics);
let source_ast: syn::File = syn::parse_quote! {
#![allow(unused_crate_dependencies, missing_docs)]
#[allow(unused)]
fn __hfplus_runtime<'a>(__hydroflow_plus_trybuild_cli: &'a hydroflow_plus::util::deploy::DeployPorts<hydroflow_plus_deploy::HydroflowPlusMeta>) -> hydroflow_plus::Hydroflow<'a> {
#(#extra_stmts)*
#tokens
}
#[tokio::main]
async fn main() {
let ports = hydroflow_plus::util::deploy::init_no_ack_start().await;
let flow = __hfplus_runtime(&ports);
println!("ack start");
hydroflow_plus::util::deploy::launch_flow(flow).await;
}
};
source_ast
}
pub fn create_trybuild(
source: &str,
bin: &str,
) -> Result<(PathBuf, PathBuf, Option<Vec<String>>), trybuild_internals_api::error::Error> {
let Metadata {
target_directory: target_dir,
workspace_root: workspace,
packages,
} = cargo::metadata()?;
let source_dir = cargo::manifest_dir()?;
let mut source_manifest = dependencies::get_manifest(&source_dir)?;
source_manifest.dev_dependencies.clear();
let mut features = features::find();
let path_dependencies = source_manifest
.dependencies
.iter()
.filter_map(|(name, dep)| {
let path = dep.path.as_ref()?;
if packages.iter().any(|p| &p.name == name) {
None
} else {
Some(PathDependency {
name: name.clone(),
normalized_path: path.canonicalize().ok()?,
})
}
})
.collect();
let crate_name = source_manifest.package.name.clone();
let project_dir = path!(target_dir / "hfplus_trybuild" / crate_name /);
fs::create_dir_all(&project_dir)?;
let project_name = format!("{}-hfplus-trybuild", crate_name);
let manifest = Runner::make_manifest(
&workspace,
&project_name,
&source_dir,
&packages,
&[],
source_manifest,
)?;
if let Some(enabled_features) = &mut features {
enabled_features.retain(|feature| {
manifest.features.contains_key(feature)
&& feature != "default"
&& feature != "stageleft_devel"
});
}
let project = Project {
dir: project_dir,
source_dir,
target_dir,
name: project_name,
update: Update::env()?,
has_pass: false,
has_compile_fail: false,
features,
workspace,
path_dependencies,
manifest,
keep_going: false,
};
let manifest_toml = toml::to_string(&project.manifest)?;
fs::write(path!(project.dir / "Cargo.toml"), manifest_toml)?;
fs::create_dir_all(path!(project.dir / "src" / "bin"))?;
let out_path = path!(project.dir / "src" / "bin" / format!("{bin}.rs"));
if !out_path.exists() || fs::read_to_string(&out_path)? != source {
fs::write(
path!(project.dir / "src" / "bin" / format!("{bin}.rs")),
source,
)?;
}
let workspace_cargo_lock = path!(project.workspace / "Cargo.lock");
if workspace_cargo_lock.exists() {
let _ = fs::copy(workspace_cargo_lock, path!(project.dir / "Cargo.lock"));
} else {
let _ = cargo::cargo(&project).arg("generate-lockfile").status();
}
let workspace_dot_cargo_config_toml = path!(project.workspace / ".cargo" / "config.toml");
if workspace_dot_cargo_config_toml.exists() {
let dot_cargo_folder = path!(project.dir / ".cargo");
fs::create_dir_all(&dot_cargo_folder)?;
let _ = fs::copy(
workspace_dot_cargo_config_toml,
path!(dot_cargo_folder / "config.toml"),
);
}
Ok((
project.dir.as_ref().into(),
path!(project.target_dir / "hfplus_trybuild"),
project.features,
))
}